.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. JDBC工具类实现登陆验证-Java(新手)

    JDBC工具类: package cn.chuang.JdbcDome; import java.sql.*; public class JdbcUtilss { private static fin ...

  2. ReentrantReadWriteLock源码探究

    ReentrantReadWriteLock实现了可重入的读锁和写锁,其中读锁是共享锁,写锁是互斥锁.与ReentrantLock类似,ReentrantReadWriteLock也提供了公平锁和非公 ...

  3. HTTP 错误 500.21 模块 IIS Web Core

    如果出现如下图错误 就是iis没有安装Web Core模块 下载并安装DotNetCore.1.0.4_1.1.1-WindowsHosting.exe 安装完成之后会出现如下 证明安装成功.网站也可 ...

  4. logstash设置从文件读取的重要参数说明及如何强置重新读取

    问题描述: 如果运行logstash时从文件读取数据时,就会遇到一个问题,如果读取的目标文件未经修改,而仅修改了conf文件,则即使重新运行logstash,或是执行时使用-r时输出也无法更新. 解决 ...

  5. TensorFlow系列专题(十四): 手把手带你搭建卷积神经网络实现冰山图像分类

    目录: 冰山图片识别背景 数据介绍 数据预处理 模型搭建 结果分析 总结 一.冰山图片识别背景 这里我们要解决的任务是来自于Kaggle上的一道赛题(https://www.kaggle.com/c/ ...

  6. vscode vue 模版生成,vue 一键生成

    vscode vue 模版 继上篇文章(vue 格式化),顺便记录下 vue 模版生成.图片就不在贴了,如果有找不到 vscode 插件商店的可以访问上篇文章. 一.安装 VueHelper 在 vs ...

  7. Mac下安装安装selenium与安装chromedriver安装

    开发环境:MacOS,Python3.7 1. 安装selenium 可以使用pip安装(pip install selenium)或者使用pycharm进行安装下载 2. 运行如下代码: from ...

  8. [noip模拟]改造二叉树<LIS>

    1.改造二叉树 [题目描述] 小Y在学树论时看到了有关二叉树的介绍:在计算机科学中,二叉树是每个结点最多有两个子结点的有序树.通常子结点被称作“左孩子”和“右孩子”.二叉树被用作二叉搜索树和二叉堆.随 ...

  9. JavaScript实现哈希表

    JavaScript实现哈希表 一.哈希表简介 1.1.认识哈希表 哈希表通常是基于数组实现的,但是相对于数组,它存在更多优势: 哈希表可以提供非常快速的插入-删除-查找操作: 无论多少数据,插入和删 ...

  10. Python第十三章-网络编程

    网络编程 一.网络编程基础 python 的网络编程模块主要支持两种Internet协议: TCP 和 UDP. 1.1通信协议 通信协议也叫网络传输协议或简称为传送协议(Communications ...