使用AspectCore动态代理
前言
最近越来越多的同学关注到AspectCore,并且提出不少中肯的建议,其中最多的提议是希望能够看到更多的关于AspectCore使用方式的文章和Demo。那么在这篇文章里,我们就来聊聊AspectCore核心之一的动态代理。
动态代理
在.NET平台中,静态织入和动态代理是实现AOP的两种方式。其中静态织入在编译时通过在MSBiuld执行自定义的Build Task来拦截编译过程,在生成的程序集里插入自己的IL。而动态代理则是在运行时通过Emit技术生成动态程序集和动态代理类型从而对目标方法进行拦截。不管那种方式,都需要对MSIL有足够的理解,如果读者想要学习MSIL相关的技术,我在这里推荐《NET探秘MSIL权威指南》一书。
AspectCore使用了动态代理作为AOP的实现,而不使用理论上性能更优的静态织入实现,是由于个人觉得动态代理方式可以做到更好的IoC进行集成并且能够在切面中获取更多的运行时元数据信息,并且在经过不断优化后,AspectCore动态代理的性能已经不落后静态织入的实现方式。
如何使用
在之前的文章里,只是简单的介绍了AspectCore,导致了很多同学不知道如何在项目里使用AspectCore(^~^,求轻拍~)。下面就来讲一下如何在IoC环境和非IoC环境里使用AspectCore的AOP。
首先通过nuget获取AspectCore:
Install-Package AspectCore.Core
AspectCore中动态代理api在AspectCore.DynamicProxy命名空间中,所以我们需要先引入命名空间
using AspectCore.DynamicProxy;
在非IoC环境中,只使用AOP的话,AspectCore提供了ProxyGeneratorBuilder作为代理生成器创建的入口
ProxyGeneratorBuilder proxyGeneratorBuilder = new ProxyGeneratorBuilder();
IProxyGenerator proxyGenerator = proxyGeneratorBuilder.Build();
IProxyGenerator提供了CreateClassProxy方法创建class代理和CreateInterfaceProxy方法创建interface代理,创建的代理类被定义在命名为AspectCore.DynamicProxy.Generator的动态程序集中,并且代理类使用AspectCore.DynamicGenerated命名空间。
我们先来定义一个简单的拦截器,接着定义一个interface和它的简单实现,并创建interface的代理:
class Program
{
static void Main(string[] args)
{
ProxyGeneratorBuilder proxyGeneratorBuilder = new ProxyGeneratorBuilder();
IProxyGenerator proxyGenerator = proxyGeneratorBuilder.Build();
SampleInterface sampleInterface = proxyGenerator.CreateInterfaceProxy<SampleInterface,SampleClass>();
Console.WriteLine(sampleInterface);
sampleInterface.Foo();
Console.ReadKey();
}
}
public class SampleInterceptor : AbstractInterceptorAttribute
{
public override Task Invoke(AspectContext context, AspectDelegate next)
{
Console.WriteLine("call interceptor");
return context.Invoke(next);
}
}
public class SampleClass : SampleInterface
{
public virtual void Foo() { }
}
[SampleInterceptor]
public interface SampleInterface
{
void Foo();
}
将会输出:
AspectCore.DynamicGenerated.SampleInterface1
call interceptor
同时,IProxyGenerator提供了若干重载的扩展方法来创建已有类或接口实例的代理,可在ProxyGeneratorExtensions中找到并使用它们。
在IoC中使用AspectCore.DynamicProxy
AspectCore在设计之初就考虑AOP和IoC的集成使用,并提供AOP抽象接口以兼容不同IoC,目前已实现和AspectCore.DynamicProxy集成的IoC框架有:
- AspectCore.Injector(AspectCore Framework的内置IoC)
- Microsoft.Extensions.DependencyInjection(Asp.Net Core的内置DI框架)
- Autofac
下面我们分别看一下在三个IoC中如何使用AspectCore.DynamicProxy。
AspectCore.Injector
AspectCore.Injector中内置了对AspectCore.DynamicProxy的支持,所以我们可以直接使用它:
IServiceContainer serviceContainer = new ServiceContainer();
serviceContainer.AddType<SampleInterface, SampleClass>();
IServiceResolver serviceResolver = serviceContainer.Build();
SampleInterface sampleInterface = serviceResolver.Resolve<SampleInterface>();
Console.WriteLine(sampleInterface);
sampleInterface.Foo();
输出:
AspectCore.DynamicGenerated.SampleClass
call interceptor
Microsoft.Extensions.DependencyInjection
AspectCore提供AspectCore.Extensions.DependencyInjection包集成Microsoft.Extensions.DependencyInjection和AspectCore.DynamicProxy。
通过nuget获取:
Install-Package AspectCore.Extensions.DependencyInjection
AspectCore提供了针对IServiceCollection的扩展方法AddDynamicProxy注册动态代理的接口和相关拦截器配置,并需要使用BuildAspectCoreServiceProvider创建被DynamicProxy接管的ServiceProvider:
IServiceCollection services = new ServiceCollection();
services.AddTransient<SampleInterface, SampleClass>();
services.AddDynamicProxy();
IServiceProvider serviceProvider = services.BuildAspectCoreServiceProvider();
SampleInterface sampleInterface = serviceProvider.GetService<SampleInterface>();
Console.WriteLine(sampleInterface);
sampleInterface.Foo();
输出:
AspectCore.DynamicGenerated.SampleClass
call interceptor
Autofac
AspectCore提供AspectCore.Extensions.Autofac包集成Autofac和AspectCore.DynamicProxy。
通过nuget获取:
Install-Package AspectCore.Extensions.Autofac
AspectCore提供了针对ContainerBuilder的扩展方法RegisterDynamicProxy注册动态代理的接口和相关拦截器配置
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<SampleClass>().As<SampleInterface>();
builder.RegisterDynamicProxy();
var container = builder.Build();
SampleInterface sampleInterface = container.Resolve<SampleInterface>();
Console.WriteLine(sampleInterface);
sampleInterface.Foo();
输出:
AspectCore.DynamicGenerated.SampleClass
call interceptor
有问题反馈
如果您有任何问题,请提交 Issue 给我们。
Github : https://github.com/dotnetcore/AspectCore-Framework
AspectCore QQ群: 306531723
使用AspectCore动态代理的更多相关文章
- AspectCore动态代理中的拦截器详解(一)
前言 在上一篇文章使用AspectCore动态代理中,简单说明了AspectCore.DynamicProxy的使用方式,由于介绍的比较浅显,也有不少同学留言询问拦截器的配置,那么在这篇文章中,我们来 ...
- .NET 下基于动态代理的 AOP 框架实现揭秘
.NET 下基于动态代理的 AOP 框架实现揭秘 Intro 之前基于 Roslyn 实现了一个简单的条件解析引擎,想了解的可以看这篇文章 https://www.cnblogs.com/weihan ...
- 实现一个简单的基于动态代理的 AOP
实现一个简单的基于动态代理的 AOP Intro 上次看基于动态代理的 AOP 框架实现,立了一个 Flag, 自己写一个简单的 AOP 实现示例,今天过来填坑了 目前的实现是基于 Emit 来做的, ...
- JDK动态代理
一.基本概念 1.什么是代理? 在阐述JDK动态代理之前,我们很有必要先来弄明白代理的概念.代理这个词本身并不是计算机专用术语,它是生活中一个常用的概念.这里引用维基百科上的一句话对代理进行定义: A ...
- AOP之Castle DynamicProxy 动态代理
这里主要介绍使用castle这个动态代理,在.net一些开源的框架里可以找到它的影子,就连微软的rchard也是使用这个进行方法拦截等可以基于这个进行方法拦截,在这个方面PostSharp算是比较好用 ...
- java动态代理的2种实现方式
java的动态代理在接java的api上有说明,这里就不写了.我理解的代理: 对特定接口中特定方法的功能进行扩展,这就是代理.代理是通过代理实例关联的调用处理程序对象调用方法. 下面通过一个例子看一下 ...
- JDK动态代理实现原理
之前虽然会用JDK的动态代理,但是有些问题却一直没有搞明白.比如说:InvocationHandler的invoke方法是由谁来调用的,代理对象是怎么生成的.直到看了他的文章才彻底明白,附网址:htt ...
- java中动态代理的实现
动态代理的实现 使用的模式:代理模式. 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问.类似租房的中介. 两种动态代理: (1)jdk动态代理,jdk动态代理是由Java内部的反射机制 ...
- 静态代理和利用反射形成的动态代理(JDK动态代理)
代理模式 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 静态代理 1.新建 ...
随机推荐
- ASP.NET MVC AJAX的调用示例
@{ ViewBag.Title = "Home Page"; //下面引用Jquery和unobtrusive-ajax } @Scripts.Render("~/bu ...
- selenium python grid
学习自动化一直都是在本机操作,感觉这样能够减少工作量确实很少.最近研究了一下分布式操作. 开始的想法是,我在一台机器上启动脚本,然后让脚本在不同机器的不同版本的浏览器上进行跑脚本. 需要准备的东西: ...
- Python实现采集wordpress整站数据的爬虫
最近爱上了python,就非常喜欢使用python来练手,在上次的基础上完善一下代码,实现采集wordpress程序的网站的整站数据的爬虫程序,本站也是采用的wordpress,我就拿吾八哥网(htt ...
- 深入浅出 SpringMVC - 1
前言: 本篇笔记是LZ在之前学习 SpringMVC 框架时所的记录,分两篇分享,此篇为基础篇,包括 SpringMVC 环境在 Eclipse 中的搭建,SpringMVC 的 HelloWorld ...
- 推荐系统架构-(附ppt&代码)
Part1.乐视网视频推荐系统 推荐系统:和传统的推荐系统架构无异(基础建模+规则) 数据模块特点:用户反馈服务数据->kv 缓存->log存储 行为日志->解析/聚合->se ...
- 【转】嵌入式C语言调试开关
在调试程序时,经常会用到assert和printf之类的函数,我最近做的这个工程里就有几百个assert,在你自认为程序已经没有bug的时候,就要除去这些调试代码,应为系统在正常运行时这些用于调试的信 ...
- 【NOIP2016 Day1 T1】玩具谜题
原题:https://www.luogu.org/problemnew/show/P1563 题目大意:有N个人围成一个圈,给定一串未化简的物品移动关系,要求你通过这些未化简的关系以及起始段的编号,求 ...
- Mysql Show ProcessList命令
每个MySql连接,或者叫线程,在任意一个给定的时间都有一个状态来标识正在进行的事情.可以使用 SHOW [FULL] PROCESSLIST 命令来查看哪些线程正在运行,及其查询状态,Command ...
- Java基础总结--变量、运算符总结
---变量基本概述----变量作用:就是用来存储数据变量的声明:变量类型 变量名;变量类型---区分不同类型的数据,变量名--按名访问变量变量名(规则):见名识意,第一个字母小写后面驼峰规则变量的作用 ...
- net start mongodb 服务名无效解决方案
net start mongodb 服务名无效 或者 net start mongodb 发生错误5,拒绝访问.是因为没有用管理员权限运行cmd. 解决方案:在window中,在搜索框输入cmd后,在 ...