2019-01-23 17:19 by 张子浩, ... 阅读, ... 评论, 收藏, 编辑
在软件业, AOP 为 Aspect Oriented Programming 的缩写, 意为: 面向切面编程, 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP 是 https://baike.baidu.com/item/OOP 的延续, 是软件开发中的一个热点, 是函数式编程的一种衍生范型. 利用 AOP 可以对业务逻辑的各个部分进行隔离, 从而使得业务逻辑各部分之间的耦合度降低, 提高程序的可重用性, 同时提高了开发的效率.
在. NET Core 中比较好的 AOP 框架有一个叫做 Aspect 的这样的一个框架, 它是一个国产的! 如何引入 AspectCore? 可以直接 nuget.
这 AspectCore 中需要创建一个拦截器一般继承自 AbstractInterceptorAttribute. 并且实现它的 Invoke 方法 .
其中第一个参数是上下文, next 是执行的委托方法, 通过这个委托可以执行被拦截的方法.
- // 每个被拦截的方法中执行
- public async override Task Invoke(AspectContext context, AspectDelegate next)
- {
- try
- {
- Console.WriteLine("Before service call");
- await next(context);
- }
- catch (Exception)
- {
- Console.WriteLine("Service threw an exception!");
- throw;
- }
- finally
- {
- Console.WriteLine("After service call");
- }
- }
首先我们可以创建一个需要被代理拦截的类 (必须是 public 方法是虚方法且被标记, 也必须使用 MVC 中的 Filter 命名规范). 这个方法也可以是异步的!
- public class Person
- {
- [CustomInterceptor]
- public virtual void Say(string msg)
- {
- Console.WriteLine("service calling..."+msg);
- }
- }
如何进行代理? 需要通过 ProxyGeneratorBuilder 来代理对象, 注意 p 指向的对象是 AspectCore 生成的 Person 的动态子类的对象, 直接 new Person 是无法被拦截的.
- static void Main(string[] args)
- {
- ProxyGeneratorBuilder proxyGeneratorBuilder = new ProxyGeneratorBuilder();
- using (IProxyGenerator proxyGenerator = proxyGeneratorBuilder.Build())
- {
- Person p = proxyGenerator.CreateClassProxy<Person>();
- p.Say("zaranet");
- }
- }
上面说到我们不可以直接 new 这个 person, 那现在我们调试一下, 一探究竟!!! 我们看看这个 p 是个什么类型.
噫? 为什么这个 p 不是 AspectPollyIdn.Person? 而是 AspectCore.DynamicGenerated.Person? 不妨把这个 p 的父类给打印出来, 来瞅瞅.
- static void Main(string[] args)
- {
- ProxyGeneratorBuilder proxyGeneratorBuilder = new ProxyGeneratorBuilder();
- using (IProxyGenerator proxyGenerator = proxyGeneratorBuilder.Build())
- {
- Person p = proxyGenerator.CreateClassProxy<Person>();
- Console.WriteLine(p.GetType().BaseType);
- p.Say("zaranet");
- }
- }
现在的对象是我们了, 也就是它的父类, 那这个时候你就绝对要明白了, 为什么我们的被代理类是虚方法, 也就是说它用子类类重写了我们被代理类的虚方法, 也就实现了 AOP, 那么呢这也就是 Aspect.Core 的原理. 大概简单的就是这样.
现在你已经了解了 AspectCore 的原理了, 但回头发现每次来创建这些对象都非常繁琐, 我们只想去使用 AspectCore 通过 CreateClassProxy() 来创建我们想要的代理对象, 那么现在我们可以使用 AspNetCore 的依赖注入解决这个问题.
首先呢, 我们引用 AspectCore.Extensions.DependencyInjection, 这是 AspectCore 给我们的一个 DI 框架. 再把 Startup 中的 ConfigureServices 进行改造.
public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.AddSingleton<Person>(); return services.BuildAspectInjectorProvider(); }
随便创建一个类 继承与 AbstractInterceptorAttribute , 重写方法, 再添加一个 Person.
public class Person { [CustomInterceptor] public virtual void Say(string msg) { // } }
在 API 中重载进行依赖注入. 下面我们进行 postman 进行测试, 因为已经关闭了浏览器浏览.
private Person p; public ValuesController(Person p) { this.p = p; }
OK, 成功.
来源: https://www.cnblogs.com/ZaraNet/p/10308706.html