.NET 下基于动态代理的 AOP 框架实现揭秘

Intro

之前基于 Roslyn 实现了一个简单的条件解析引擎,想了解的可以看这篇文章 https://www.cnblogs.com/weihanli/p/roslyn-based-condition-eval-engine.html

执行过程中会根据条件的不同会在运行时创建一个类,每一次创建都会生成一个新的程序集,我觉得这样实现的话可能会导致加载的程序集越来越多,虽然目前我们的使用场景下不会有很多,而且相同的条件只会生成一次,还是觉得这样不是特别好,此时想起来了一些 AOP 框架,Aspect.Core/Castle/DispatchProxy ,他们这些 AOP 框架会生成一些代码类,好像也没有生成很多额外的程序集,于是打算看看这些 AOP 框架的实现,看看它们是如何生成动态代理类的

动态代理实现原理

看了这三个 AOP 框架的实现代码之后,实现原理基本都是一样的

都是通过创建一个 DynamicAssembly 之后在这个 DynamicAssemly 中创建要动态生成代理类,通过 Emit 创建要生成动态代理类的方法/属性等

来个小示例

多说不如来点代码示例:

internal class ProxyUtil
{
private const string ProxyAssemblyName = "Aop.DynamicGenerated";
private static readonly ModuleBuilder _moduleBuilder;
private static readonly ConcurrentDictionary<string, Type> _proxyTypes = new ConcurrentDictionary<string, Type>(); static ProxyUtil()
{
// 定义一个动态程序集
var asmBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(ProxyAssemblyName), AssemblyBuilderAccess.Run);
// 创建一个动态模块,后面创建动态代理类通过这个来创建
_moduleBuilder = asmBuilder.DefineDynamicModule("Default");
} public static Type CreateInterfaceProxy(Type interfaceType)
{
var proxyTypeName = $"{ProxyAssemblyName}.{interfaceType.FullName}";
var type = _proxyTypes.GetOrAdd(proxyTypeName, name =>
{
// 定义要创建的类型,并实现指定类型接口
var typeBuilder = _moduleBuilder.DefineType(proxyTypeName, TypeAttributes.Public, typeof(object), new[] { interfaceType });
// 定义一个默认的构造方法
typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
// 获取接口中定义的方法
var methods = interfaceType.GetMethods(BindingFlags.Instance | BindingFlags.Public);
foreach (var method in methods)
{
// 在动态类中定义方法,方法名称,返回值和签名与接口方法保持一致
var methodBuilder = typeBuilder.DefineMethod(method.Name
, MethodAttributes.Public | MethodAttributes.Virtual,
method.CallingConvention,
method.ReturnType,
method.GetParameters()
.Select(p => p.ParameterType)
.ToArray()
); // 获取 ILGenerator,通过 Emit 实现方法体
var ilGenerator = methodBuilder.GetILGenerator();
ilGenerator.EmitWriteLine($"method [{method.Name}] is invoking...");
ilGenerator.Emit(OpCodes.Ret); // 定义方法实现
typeBuilder.DefineMethodOverride(methodBuilder, method);
} return typeBuilder.CreateType();
});
return type;
}
}

通过上面的定义我们可以创建一个简单的代理类,然后定义一个 ProxyGenerator 来创建代理

public class ProxyGenerator
{
public static readonly ProxyGenerator Instance = new ProxyGenerator(); public object CreateInterfaceProxy(Type interfaceType)
{
var type = ProxyUtil.CreateInterfaceProxy(interfaceType);
return Activator.CreateInstance(type);
}
}
// 定义泛型扩展
public static class ProxyGeneratorExtensions
{
public static TInterface CreateInterfaceProxy<TInterface>(this ProxyGenerator proxyGenerator) =>
(TInterface)proxyGenerator.CreateInterfaceProxy(typeof(TInterface));
}

使用示例:

var testService = ProxyGenerator.Instance.CreateInterfaceProxy<ITestService>();
testService.Test();

可以看到这个类型就是我们动态创建的一个类型,输出结果也是我们定义在代理类中的结果

More

.NET 中的基于动态代理的 AOP 也是这样实现的,实现的原理大致就是这样,这个示例比较简单还没有涉及 AOP ,这只是一个简单的动态代理示例 ,AOP 只需要在原始方法执行的逻辑上包装一层拦截器增加对拦截器的处理和调用即可,暂时还没实现,后面有机会再分享

Reference

.NET 下基于动态代理的 AOP 框架实现揭秘的更多相关文章

  1. 实现一个简单的基于动态代理的 AOP

    实现一个简单的基于动态代理的 AOP Intro 上次看基于动态代理的 AOP 框架实现,立了一个 Flag, 自己写一个简单的 AOP 实现示例,今天过来填坑了 目前的实现是基于 Emit 来做的, ...

  2. 动态代理到基于动态代理的AOP

    动态代理,是java支持的一种程序设计方法. 动态代理实现中有两个重要的接口和类,分别是InvocationHandler(interface),Proxy(class). 要实现动态代理,必须要定义 ...

  3. .Net 框架实现AOP(动态代理实现AOP,本文为翻译)

    在上一节,我们将静态实现AOP,但是对于一个大型项目,要想为每个类,每个方法都去实现AOP ,进行日志记录和权限验证似乎是不可能的. 即使可能对于成百上千个类维护,也是很难维护.所以今天的主题就是如标 ...

  4. 动态代理的两种方式,以及区别(静态代理、JDK与CGLIB动态代理、AOP+IoC)

    Spring学习总结(二)——静态代理.JDK与CGLIB动态代理.AOP+IoC   目录 一.为什么需要代理模式 二.静态代理 三.动态代理,使用JDK内置的Proxy实现 四.动态代理,使用cg ...

  5. Java动态代理-->Spring AOP

    引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓“登高必自卑,涉远必自迩”.以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系列分别介绍这些Jav ...

  6. Java 动态代理与AOP

    动态代理与AOP 代理模式 代理模式给某一个目标对象(target)提供代理对象(proxy),并由代理对象控制对target对象的引用. 模式图: 代理模式中的角色有: 抽象对象角色(Abstrac ...

  7. Java 动态代理及AOP实现机制

    AOP实现机制http://www.iteye.com/topic/1116696 AOP: (Aspect Oriented Programming) 面向切面编程AOP包括切面(aspect).通 ...

  8. DispatchProxy实现动态代理及AOP

    DispatchProxy类是DotnetCore下的动态代理的类,源码地址:Github,官方文档:MSDN.主要是Activator以及AssemblyBuilder来实现的(请看源码分析),园子 ...

  9. Java-JDK动态代理(AOP)使用及实现原理分析

    Java-JDK动态代理(AOP)使用及实现原理分析 第一章:代理的介绍 介绍:我们需要掌握的程度 动态代理(理解) 基于反射机制 掌握的程度: 1.什么是动态代理? 2.动态代理能够做什么? 后面我 ...

随机推荐

  1. JavaScript每日学习日记(2)

    8.13.2019 1. 正则表达式常见字符串方法: search( ) , replace( ) var str = "Visit Website"; var n = str.s ...

  2. python深浅拷贝&垃圾回收&上下文管理(with语句)

    深浅拷贝 在Python中使用copy模块用于对象的拷贝操作. 该模块提供了两个主要的方法:浅拷贝 copy.copy() 深拷贝 copy.deepcopy() 1.浅拷贝(copy) 浅拷贝: 不 ...

  3. 记一次RSA解密过程

    有问题可以评论 openssl rsa -pubin -text -modulus -in warmup -in pub.key

  4. Python进制的转换

    Python整数能够以十六进制,八进制和二进制来编写,作为一般以10位基数的十进制计数法的补充. 一: 上面三种进制的常用表示  >>> 0o1, 0o20, 0o377 # 八进制 ...

  5. MySQL学习(4)

    一 视图 预先定义一种对应关系,如:temp_table <-----> select * from class where student_id >10,那么这种对应关系叫做视图. ...

  6. python ndarray与pandas series相互转换,ndarray与dataframe相互转换

    https://blog.csdn.net/qq_33873431/article/details/98077676

  7. 动态规划(Dynamic Programming)算法与LC实例的理解

    动态规划(Dynamic Programming)算法与LC实例的理解 希望通过写下来自己学习历程的方式帮助自己加深对知识的理解,也帮助其他人更好地学习,少走弯路.也欢迎大家来给我的Github的Le ...

  8. MATLAB中mean的用法

    https://blog.csdn.net/wangyang20170901/article/details/78745587 MATLAB中mean的用法 转载仙女阳 最后发布于2017-12-07 ...

  9. python之面向对象的成员,方法,属性,异常处理

    一.类的私有成员 1. 类中的私有成员是什么? 私有:只有满足一部分条件的才能使用 私有类的属性 私有对象的属性 私有方法 正常状态 class B: school_name = '老男孩教育' de ...

  10. OpenCV-Python BRIEF(二进制的鲁棒独立基本特征) | 四十二

    目标 在本章中,我们将看到BRIEF算法的基础知识 理论 我们知道SIFT使用128维矢量作为描述符.由于它使用浮点数,因此基本上需要512个字节.同样,SURF最少也需要256个字节(用于64像素) ...