写点什么

动手造轮子:实现一个简单的 -AOP- 框架

  • 2021 年 11 月 11 日
  • 本文字数:2055 字

    阅读完需:约 7 分钟

IProxyTypeFactory

用来生成代理类型,默认提供了基于 Emit 动态代理的实现,基于接口设计,可以扩展为其他实现方式


接口定义如下:


public interface IProxyTypeFactory{Type CreateProxyType(Type serviceType);


Type CreateProxyType(Type serviceType, Type implementType);}

IProxyFactory

用来生成代理实例,默认实现是基于?IProxyTypeFactory?生成代理类型之后创建实例


接口定义如下:


public interface IProxyFactory{object CreateProxy(Type serviceType, object[] arguments);


object CreateProxy(Type serviceType, Type implementType, params object[] arguments);


object CreateProxyWithTarget(Type serviceType, object implement, object[] arguments);}

IInvocation

执行上下文,默认实现就是方法执行的上下文,包含了代理方法信息、被代理的方法信息、方法参数,返回值以及用来自定义扩展的一个?Properties?属性


public interface IInvocation{MethodInfo ProxyMethod { get; }


object ProxyTarget { get; }


MethodInfo Method { get; }


object Target { get; }


object[] Arguments { get; }


Type[] GenericArguments { get; }


object ReturnValue { get; set; }


Dictionary<string, object> Properties { get; }}

IInterceptor

拦截器,用来定义公用的处理逻辑,方法拦截处理方法


接口定义如下:


public interface IInterceptor{Task Invoke(IInvocation invocation, Func<Task> next);}


invocation?是方法执行的上下文,next?代表后续的逻辑处理,类似于 asp.net core 里的?next?,如果不想执行方面的方法不执行?next?逻辑即可

IInterceptorResolver

用来根据当前的执行上下文获取到要执行的拦截器,默认是基于 FluentAPI 的实现,但是如果你特别想用基于 Attribute 的也是可以的,默认提供了一个?AttributeInterceotorResovler,你也可以自定义一个适合自己的?InterceptorResolver


public interface IInterceptorResolver{IReadOnlyList<IInterceptor> ResolveInterceptors(IInvocation invocation);}

IInvocationEnricher

上面?IInvocation?的定义中有一个用于扩展的?Properties,这个?enricher?主要就是基于?Properties?来丰富执行上下文信息的,比如说记录?TraceId?等请求链路追踪数据,构建方法执行链路等


public interface IEnricher<in TContext>{void Enrich(TContext context);}public interface IInvocationEnricher : IEnricher<IInvocation>{}

AspectDelegate

AspectDelegate?是用来将构建要执行的代理方法的方法体的,首先执行注册的?InvocationEnricher,丰富上下文信息,然后根据执行上下文获取要执行的拦截器,构建一个执行委托,生成委托使用了之前分享过的?PipelineBuilder?构建中间件模式的拦截器,执行拦截器逻辑


// apply enrichersforeach (var enricher in FluentAspects.AspectOptions.Enrichers){try{enricher.Enrich(invocation);}catch (Exception ex){InvokeHelper.OnInvokeException?.Invoke(ex);}}


// get delegatevar builder = PipelineBuilder.CreateAsync(completeFunc);f


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


oreach (var interceptor in interceptors){builder.Use(interceptor.Invoke);}return builder.Build();


更多信息可以参考源码:?https://github.com/WeihanLi/WeihanLi.Common/blob/dev/src/WeihanLi.Common/Aspect/AspectDelegate.cs

使用示例

推荐和依赖注入结合使用,主要分为以微软的注入框架为例,有两种使用方式,一种是手动注册代理服务,一种是自动批量注册代理服务,来看下面的实例就明白了

手动注册代理服务

使用方式一,手动注册代理服务:


为了方便使用,提供了一些?AddProxy?的扩展方法:


IServiceCollection services = new ServiceCollection();services.AddFluentAspects(options =>{// 注册拦截器配置 options.NoInterceptProperty<IFly>(f => f.Name);


options.InterceptAll().With<LogInterceptor>();options.InterceptMethod<DbContext>(x => x.Name == nameof(DbContext.SaveChanges)|| x.Name == nameof(DbContext.SaveChangesAsync)).With<DbContextSaveInterceptor>();options.InterceptMethod<IFly>(f => f.Fly()).With<LogInterceptor>();options.InterceptType<IFly>().With<LogInterceptor>();


// 注册 InvocationEnricheroptions.WithProperty("TraceId", "121212");});// 使用 Castle 生成代理 services.AddFluentAspects(options =>{// 注册拦截器配置 options.NoInterceptProperty<IFly>(f => f.Name);


options.InterceptAll().With<LogInterceptor>();options.InterceptMethod<DbContext>(x => x.Name == nameof(DbContext.SaveChanges)|| x.Name == nameof(DbContext.SaveChangesAsync)).With<DbContextSaveInterceptor>();options.InterceptMethod<IFly>(f => f.Fly()).With<LogInterceptor>();options.InterceptType<IFly>().With<LogInterceptor>();


// 注册 InvocationEnricher

评论

发布
暂无评论
动手造轮子:实现一个简单的-AOP-框架