浅析DispatchProxy动态代理AOP
浅析DispatchProxy动态代理AOP(代码源码)
最近学习了一段时间Java,了解到Java实现动态代理
AOP主要分为两种方式JDK、CGLIB,我之前使用NET实现AOP切面编程,会用Filter拦截器、Attribute特性、中间件、继承父类重写父类方法。
经过查找资料接触到了(牛逼不分先后)
DispatchProxy抽象类源码地址Dora开源地址castleproject开源地址CZGL.AOP开源地址
DispatchProxy类介绍
DispatchProxy源码,主要使用了Emit类库直接编写IL语言,动态生成类,和方法,然后会调用Invoke方法(性能很高,几乎和我们写的C#编译成IL没有区别),我们继承了DispatchProxy抽象类,重写Invoke方法,具体实现就可以自定义了。
DispatchProxy源码
DispatchProxy主要是
Activator(文档地址)以及AssemblyBuilder(文档地址)实现,
Activator类在运行时可以动态构造对象AssemblyBuilder类在运行时可以动态获取和设置专用字段的属性、初始化专用字段的构造函数,动态执行方法并返回结果。
// 动态代理生成类
internal static class DispatchProxyGenerator
{
// 动态代理容器(保存已经生成过的代理)
private static readonly Dictionary> s_baseTypeAndInterfaceToGeneratedProxyType = new Dictionary>();
private static readonly ProxyAssembly s_proxyAssembly = new ProxyAssembly();
private static readonly MethodInfo s_dispatchProxyInvokeMethod = typeof(DispatchProxy).GetTypeInfo().GetDeclaredMethod("Invoke");
// 返回派生自'baseType'的代理的新实例,并实现'interfaceType'
internal static object CreateProxyInstance(Type baseType, Type interfaceType)
{
Debug.Assert(baseType != null);
Debug.Assert(interfaceType != null);
// 获取代理类型
Type proxiedType = GetProxyType(baseType, interfaceType);
// 创建实例
return Activator.CreateInstance(proxiedType, (Action
DispatchProxy拓展封装
根据前面的介绍,对DispatchProxy有了一定的了解,我们可以进行一些封装方便以后使用。
DynamicProxy动态代理类
我们创建DynamicProxy类,包装方法执行之前&执行之后的处理,主体方法报错的处理,形成一个动态代理类。
public class DynamicProxy : DispatchProxy, IScopedDependency
{
private static ILogger? _logger { get; set; }
///
/// 目标类
///
public object Target { get; set; }
///
/// 动作之后执行
///
private Action
创建IProxyHandle
我们会有很多处理实现类,每个实现类都需要实现AfterAction、BeforeAction、TargetMethodExceptionAction
public interface IProxyHandle
{
///
/// 执行之前
///
/// 目标方法参数
void AfterAction(object?[]? args);
///
/// 执行之后
///
/// 目标方法参数
/// 目标方法执行结果
void BeforeAction(object?[]? args, object resultValue);
///
/// 方法执行错误处理
///
/// 目标方法
/// 目标方法参数
/// 目标方法执行结果
void MethodExceptionAction(MethodInfo? targetMethod, object?[]? args, Exception ex);
}
创建ProxyHandleAttribute特性
这里我尝试过几种方式,通过接口或者使用特性,最终特性比较方便团队使用(接口也不错)。
///
/// 代理Aop特性
///
[AttributeUsage(AttributeTargets.Class)]
public class ProxyHandleAttribute : Attribute
{
public Type Type { get; set; }
public ProxyHandleAttribute(Type type)
{
this.Type = type;
}
}
ProxyFactory代理工厂
根据实现类获取Aop切面类型,再获取AOP工厂(
IEnumerable)中对应实现。
///
/// 代理工厂
///
public class ProxyFactory : IScopedDependency
{
private readonly IServiceProvider _serviceProvider;
private readonly IEnumerable _proxyHandleList;
private readonly DynamicProxy _dynamicProxy;
private readonly ILogger _logger;
public ProxyFactory(IEnumerable proxyHandleList,
IServiceProvider serviceProvider,
DynamicProxy dynamicProxy,
ILogger logger)
{
this._serviceProvider = serviceProvider;
this._proxyHandleList = proxyHandleList;
this._dynamicProxy = dynamicProxy;
this._logger = logger;
}
///
/// 创建代理实例
///
///
public T Create() where T : class
{
var target = _serviceProvider.GetService();
if (target == null)
{
throw new BusinessException($"执行ProxyFactory=》Create方法:{typeof(T).FullName}未注入");
}
var type = target.GetType();
var proxyHandleAttribute = type.GetCustomAttribute();
if (proxyHandleAttribute == null)
{
throw new BusinessException($"执行ProxyFactory=》Create方法:{type.FullName}需要添加ProxyHandleAttribute特性");
}
var proxyHandle = _proxyHandleList.FirstOrDefault(x => x.GetType() == proxyHandleAttribute.Type);
if (proxyHandleAttribute == null)
{
throw new BusinessException($"执行ProxyFactory=》Create方法:没有找到对应IProxyHandle接口实现");
}
//创建代理类
var proxy = _dynamicProxy.Create(target,
proxyHandle.AfterAction,
proxyHandle.BeforeAction,
proxyHandle.MethodExceptionAction,
_logger);
return proxy;
}
}
DynamicProxy使用示例
IProxyHandle实现类(ProxyHandleTest)
public class ProxyHandleTest : IProxyHandle
{
public void AfterAction(object[] args)
{
Console.WriteLine($"ProxyHandleTest=》AfterAction方法执行,args:{JsonSerializer.Serialize(args)}");
}
public void BeforeAction(object[] args, object resultValue)
{
Console.WriteLine($"ProxyHandleTest=》BeforeAction方法执行,args:{JsonSerializer.Serialize(args)},result:{resultValue}");
}
public void MethodExceptionAction(MethodInfo targetMethod, object[] args, Exception ex)
{
Console.WriteLine($"ProxyHandleTest=》MethodExceptionAction方法执行,targetMethod,:{targetMethod.Name},args:{JsonSerializer.Serialize(args)},ex:{ex.Message}");
}
}
- 准备
ITestService、TestService
public interface ITestService
{
///
/// 获取用户Id信息
///
///
int GetUserId();
void SetUserId(int userId);
}
[ProxyHandle(typeof(ProxyHandleTest))]
public class TestService : ITestService, IScopedDependency
{
public int GetUserId()
{
Console.WriteLine($"执行TestService=>GetUserId()");
return 10;
}
public void SetUserId(int userId)
{
Console.WriteLine($"执行TestService=>SetUserId({userId})");
throw new Exception("执行TestService=>SetUserId测试异常");
}
}
- 最后只需要注入
ProxyFactory
public class TestController : AbpController
{
private readonly ProxyFactory _proxyFactory;
public TestController(ProxyFactory proxyFactory)
{
_proxyFactory = proxyFactory;
}
// GET: api/
[HttpGet]
public IEnumerable Get()
{
// 从工厂获取代理类
var testService = _proxyFactory.Create();
testService.GetUserId();
return new string[] { "value1", "value2" };
}
总结
DispatchProxy实现动态代理主要是依赖Emit类库直接编写IL语言。Activator类在运行时动态构造对象。AssemblyBuilder类运行时动态一个获取和设置专用字段的属性、初始化专用字段的构造函数,可以动态执行方法并返回结果。
不管是Java还是Net实现AOP切面编程原理差不多。