最近实现了一个 AOP 框架 – FluentAspects,API 基本稳定了,写篇文章分享一下这个 AOP 框架的设计。

整体设计

概览

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 enrichers
foreach (var enricher in FluentAspects.AspectOptions.Enrichers)
{try{enricher.Enrich(invocation);}catch (Exception ex){InvokeHelper.OnInvokeException?.Invoke(ex);}
}// get delegate
var builder = PipelineBuilder.CreateAsync(completeFunc);
foreach (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>();// 注册 InvocationEnricheroptions.WithProperty("TraceId", "121212");}, builder => builder.UseCastle());services.AddTransientProxy<IFly, MonkeyKing>();
services.AddSingletonProxy<IEventBus, EventBus>();
services.AddDbContext<TestDbContext>(options =>
{options.UseInMemoryDatabase("Test");
});
services.AddScopedProxy<TestDbContext>();var serviceProvider = services.BuildServiceProvider();

批量自动注册代理服务

使用方式二,批量自动注册代理服务:

IServiceCollection services = new ServiceCollection();
services.AddTransient<IFly, MonkeyKing>();
services.AddSingleton<IEventBus, EventBus>();
services.AddDbContext<TestDbContext>(options =>
{options.UseInMemoryDatabase("Test");
});var serviceProvider = services.BuildFluentAspectsProvider(options =>{options.InterceptAll().With<TestOutputInterceptor>(output);});// 使用 Castle 来生成代理
var serviceProvider = services.BuildFluentAspectsProvider(options =>{options.InterceptAll().With<TestOutputInterceptor>(output);}, builder => builder.UseCastle());// 忽略命名空间为 Microsoft/System 的服务类型
var serviceProvider = services.BuildFluentAspectsProvider(options =>{options.InterceptAll().With<TestOutputInterceptor>(output);}, builder => builder.UseCastle(), t=> t.Namespace != null && (t.Namespace.StartWith("Microsft") ||t.Namespace.StartWith("Microsft")));

More

上面的两种方式个人比较推荐使用第一种方式,需要拦截什么就注册什么代理服务,自动注册可能会生成很多不必要的代理服务,个人还是比较喜欢按需注册的方式。

这个框架还不是很完善,有一些地方还是需要优化的,目前还是在我自己的类库中,因为我的类库里要支持 net45,所以有一些不好的设计改起来不太方便,打算迁移出来作为一个单独的组件,直接基于 netstandard2.0/netstandard2.1, 甩掉 netfx 的包袱。

最后

不管是要离职还是继续坚持,最重要的是要走出舒适区,可能我们还只是工作了两三年,没有这种感觉,但凡事要做长远打算,按照自己的节奏去走好每一步。小编为面试的小伙伴们准备了前端面试资料和前端学习思维导图及资料,免费分享给大家,希望在想走出困境或离开舒适区时,对你有帮助。


甩掉 netfx 的包袱。

最后

不管是要离职还是继续坚持,最重要的是要走出舒适区,可能我们还只是工作了两三年,没有这种感觉,但凡事要做长远打算,按照自己的节奏去走好每一步。小编为面试的小伙伴们准备了前端面试资料和前端学习思维导图及资料,免费分享给大家,希望在想走出困境或离开舒适区时,对你有帮助。

[外链图片转存中…(img-pWBdyHhe-1626928922710)]
[外链图片转存中…(img-c7Oo2PT6-1626928922711)]

点击这里免费领取上述资料

web前端开发培训培训,JavaScript运算符相关推荐

  1. web前端开发主要培训哪些内容

    想要学会web前端,最好是选择报web前端培训机构是最合适的选择,然后做好学习路线的规划,这样学起来是比较方便且快速的,下面小编就为大家详细的介绍一下web前端开发主要培训哪些内容? web前端开发主 ...

  2. 哪里有web前端开发的培训机构-选对学校很重要

    Web前端开发行业现在是非常缺乏人才的,多以很多人便希望能够参加web前端开发工程师的培训,哪里有web前端开发的培训机构呢?怎么选择一家合适的web培训机构呢. 哪里有web前端开发的培训机构-先了 ...

  3. 学web前端开发,培训和自学哪个更靠谱?

    web前端在最近这几年越来越被注重,许多公司往往花高薪还是无法找到一个令自己满意的web前端人才,所以web前端的前景还是十分不错的,而且web前端上手也简单,假如能静下心来学习,几个月的时间还是能够 ...

  4. Web前端开发HTML清华大学,清华大学出版社-图书详情-《Web前端开发——HTML5+CSS+JavaScript+ jQuery +Dreamweaver》...

    前言 Web前端开发是网站开发方向重要的专业课程,随着市场对Web前端工程师的需求增加,国内很多本专科院校正在或准备开设该课程.本书是咸阳师范学院2016年教材建设资助项目. Web前端开发涵盖多门技 ...

  5. 学web前端开发,培训靠谱还是自学靠谱

    一般网上那些,上来就说自学没啥用,培训也坑人的博主,相信没有一个是站在当事人的角度考虑这个问题. 如果你真的没有任何编程基础,自学能力也不是特别强,这种情况下,就要问问题主,那你为什么要学web前端, ...

  6. web前端开发薪资,JavaScript的字面量与变量

    随着Web应用程序功能的日益复杂和复杂,Web开发人员需要灵活的工具来满足不断增长的用户期望.好消息是,Web开发生态系统为我们提供了很多选择,老牌公司和开源社区都在竞相构建更强大的库,框架和应用程序 ...

  7. web前端开发职业培训,前端应届生如何做一个职业规划

    面试知识点 主要内容包括html,css,前端基础,前端核心,前端进阶,移动端开发,计算机基础,算法与数据结构,设计模式,项目等等. html 1.浏览器页面有哪三层构成,分别是什么,作用是什么? 2 ...

  8. 麦子学院-Web前端开发工程师系列培训教程

    麦子学院Web前端开发工程师培训-价值1万8 比传智播客讲得好 Web前端开发工程师,主要职责是利用HTML.XHTML.CSS.JAVAScript.FLASH等各种Web前端技术进行客户端产品的开 ...

  9. 北风网web前端开发培训课程 web前端开发实例视频教程下载

    web前端开发视频教程 Web前端开发工程师培训 零基础Web前端开发工程师高端培训配项目开发(月薪过万的最佳选择) 课程讲师:叮咚 课程分类:套餐推荐 适合人群:初级 课时数量:305课时 用到技术 ...

  10. web前端开发培训有哪些学习阶段

    ​ web前端技术主要针对于移动互联网是比较多的,对于零基础的同学来说前期主要学习基本的静态布局,HTML + CSS,下面是web前端开发培训有哪些学习阶段的具体内容. ​ web前端开发培训有哪些 ...

最新文章

  1. Python 进阶之路 (九) 再立Flag, 社区最全的itertools深度解析(上)
  2. java整合mybatis,springboot集成mybatis
  3. 找不到php的版本,php – 在任何版本中都找不到请求的包…
  4. SpringCache与Redis
  5. 1. Window环境下 - 开发环境的配置: (安装Android Studio 2.1)
  6. Ubuntu 命令技巧
  7. Roson的Qt之旅 #117 QTcpSocket和QUdpSocket详细介绍
  8. 如何做好数据分析师的职业规划?
  9. 小白python爬虫入门实例2—— 翻页爬取京东商城商品数据
  10. 用html制作三角形九九乘法表,用js实现打印九九乘法表
  11. 08-Httprunner-断言(validate)
  12. python获取所有a股股票代码_股票量化分析(一)获取A股列表
  13. IE5.0中的三个彩蛋(转)
  14. 一般来说,联盟链相对于公有链的优势在哪里?
  15. Android FaceBook登录问题记录
  16. phantomjs html2Image.js 网页转换图片
  17. 自由软件之父:“苹果公司罪大恶极”
  18. 蓝桥---超声波测距
  19. 2021年12月电子学会图形化一级编程题解析含答案:下雨
  20. 智能高低配电柜无线联网解决方案

热门文章

  1. Labview笔记(十)---文件IO (中)---读写 配置文件,XML文件
  2. SQL SERVER 卸载清除步骤
  3. 2019-数学建模美赛-B题翻译
  4. 低代码大势所趋,RDP报表3.0应运而生
  5. 模2运算的原理 模2加法,模2减法,模2乘法,模2除法
  6. 关于xcode中的代码比较工具
  7. java反射机制面试_java面试中面试官让你讲讲反射,应该从何讲起?
  8. 解决ojdbc7依赖下载失败
  9. ccs6.0 破解版安装教程 Code Composer Studio安装教程
  10. 在线电子词典程序框架