FluentAspects -- 基于 Fluent API 的 Aop
fluentaspects -- 基于 fluent api 的 aop
intro
上次我们做了一个简单的 aop 实现示例,但是实现起来主要是基于 attribute
来做的,对于代码的侵入性太强,于是尝试实现基于 fluent api 的方式来做 aop 。
抽象 interceptorresolver
原来获取方法执行的 interceptor 是通过 attribute
来获取的,现在我们只需要将获取 interceptor 的逻辑抽象出来就可以实现不必依赖于 attribute
了
方法执行上下文定义:
public interface iinvocation { public methodinfo proxymethod { get; } public object proxytarget { get; } public methodinfo method { get; } public object target { get; } public object[] arguments { get; } type[] genericarguments { get; } public object returnvalue { get; set; } }
方法拦截器 interceptor
接口定义:
public interface iinterceptor { task invoke(iinvocation invocation, func<task> next); }
自定义 interceptor 只需要继承这个接口实现相应的逻辑就好了
获取 iinterceptorresolver
接口定义:
public interface iinterceptorresolver { ireadonlycollection<iinterceptor> resolveinterceptors(iinvocation invocation); }
原来基于 attribute
获取 interceptor 的方式可以实现一个 attributeinterceptorresolver
想要基于 fluent api 来获取 interceptor ,只需要实现基于 fluent api 的 interceptorresolver
就可以了,具体的实现可以参考 fluentconfiginterceptorresolver
示例预览
测试服务定义:
public interface isvc1 { void invoke(); } public interface isvc2 { void invoke(); } public class svc2 : isvc2 { public void invoke() { console.writeline($"invoking in {gettype().name} ..."); } public void invoke2() { console.writeline($"invoking in {gettype().name} ..."); } } public class svc3 { public virtual void invoke() { console.writeline($"invoking in {gettype().name} ..."); } } public class svc4 { public virtual void invoke() { console.writeline($"invoking in {gettype().name} ..."); } public void invoke2() { console.writeline($"invoking2 in {gettype().name} ..."); } public virtual void invoke3() { console.writeline($"invoking3 in {gettype().name} ..."); } }
测试 interceptor
internal class loginterceptor : iinterceptor { public async task invoke(iinvocation invocation, func<task> next) { console.writeline($"invoke {invocation.proxymethod} in {gettype().name} begin"); await next(); console.writeline($"invoke {invocation.proxymethod} in {gettype().name} end"); } }
测试代码:
public static void main(string[] args) { var services = new servicecollection(); services.addfluentaspects(options => { // 为所有拦截的方法添加拦截器 options.interceptall() .with<loginterceptor>() ; // 对 svc3 类型禁用拦截器 options.nointercepttype<svc3>(); // svc4 类型的 invoke3() 方法禁用拦截器 options.nointerceptmethod<svc4>(s => s.invoke3()); }); services.addtransientproxy<svc4>(); var serviceprovider = services.buildserviceprovider(); var proxyfactory = serviceprovider.getrequiredservice<iproxyfactory>(); var svc1 = proxyfactory.createproxy<isvc1>(); svc1.invoke(); console.writeline(); var svc2 = proxyfactory.createproxy<isvc2, svc2>(); svc2.invoke(); console.writeline(); var svc3 = proxyfactory.createproxy<svc3>(); svc3.invoke(); console.writeline(); var svc4 = proxyfactory.createproxywithtarget<isvc2, svc2>(new svc2()); svc4.invoke(); console.writeline(); // 直接从注册的服务中获取 var svc5 = serviceprovider.getrequiredservice<svc4>(); svc5.invoke(); console.writeline(); svc5.invoke2(); console.writeline(); svc5.invoke3(); console.writeline(); console.writeline("finished"); console.readline(); }
输出结果预览:
more
最近十几天的时间一直在搞这个,相比之前写的示例,真正实现一个完整的 aop 框架还是要做比较多的事情的,之前的 aop 示例,没有考虑泛型,也没有什么设计,所以前面的示例只能算是一个小玩具。
在实现的过程中,参考了很多 aspectcore 的代码,有一些代码甚至是直接从 aspectcore 里抄过来的。
推荐大家有机会研究学习一下柠檬大佬的 aspectcore 的源码,这个 aop 框架的代码组织,代码细节都挺不错的。
aspectcore 源码地址: https://github.com/dotnetcore/aspectcore-framework
reference
推荐阅读
-
Java中基于Aspectwerkz的AOP
-
基于Rest的API解决方案(jersey与swagger集成)
-
基于spring的aop实现多数据源动态切换 博客分类: javaspring 动态切换springaopAbstractRoutingDataSource
-
Yii2 基于RESTful架构的 advanced版API接口开发 配置、实现、测试,yii2restful
-
Nutz:基于ASM的Nut.Aop实现 博客分类: Nutz AOPJavaGoogleIDEASSH
-
Nutz:基于ASM的Nut.Aop实现 博客分类: Nutz AOPJavaGoogleIDEASSH
-
基于JSON类型返回的API接口如果做输出校验?
-
从壹开始前后端分离【 .NET Core2.0 Api + Vue 2.0 + AOP + 分布式】框架之五 || Swagger的使用 3.3
-
从壹开始前后端分离【 .NET Core2.0 Api + Vue 2.0 + AOP + 分布式】框架之四 || Swagger的使用 3.2
-
基于tungsten API 同步mysql binlog出现EOF packet received的问题解决