浅析DispatchProxy动态代理AOP

浅析DispatchProxy动态代理AOP(代码源码)

最近学习了一段时间Java,了解到Java实现动态代理AOP主要分为两种方式JDKCGLIB,我之前使用NET实现AOP切面编程,会用Filter拦截器Attribute特性中间件继承父类重写父类方法

浅析DispatchProxy动态代理AOP

经过查找资料接触到了(牛逼不分先后)

DispatchProxy类介绍

DispatchProxy源码,主要使用了Emit类库直接编写IL语言,动态生成类,和方法,然后会调用Invoke方法(性能很高,几乎和我们写的C#编译成IL没有区别),我们继承了DispatchProxy抽象类,重写Invoke方法,具体实现就可以自定义了。

DispatchProxy源码

DispatchProxy主要是Activator(文档地址)以及AssemblyBuilder(文档地址)实现,

  • Activator 类在运行时可以动态构造对象
  • AssemblyBuilder 类在运行时可以动态获取和设置专用字段的属性、初始化专用字段的构造函数,动态执行方法并返回结果。

浅析DispatchProxy动态代理AOP

    // 动态代理生成类     internal static class DispatchProxyGenerator     {         // 动态代理容器(保存已经生成过的代理)         private static readonly Dictionary<Type, Dictionary<Type, Type>> s_baseTypeAndInterfaceToGeneratedProxyType = new Dictionary<Type, Dictionary<Type, Type>>();         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<object[]>)DispatchProxyGenerator.Invoke);         }          // 首先从代理容器中获取,如果没有进行创建         private static Type GetProxyType(Type baseType, Type interfaceType)         {             // 锁住容器             lock (s_baseTypeAndInterfaceToGeneratedProxyType)             {                 Dictionary<Type, Type> interfaceToProxy = null;                 // 判断baseType实现类类型容器中是否存在,不存在先初始化一个                 if (!s_baseTypeAndInterfaceToGeneratedProxyType.TryGetValue(baseType, out interfaceToProxy))                 {                     interfaceToProxy = new Dictionary<Type, Type>();                     s_baseTypeAndInterfaceToGeneratedProxyType[baseType] = interfaceToProxy;                 }                 Type generatedProxy = null;                 // 判断是否存在interfaceType接口类型代理类,不存在就创建一个                 if (!interfaceToProxy.TryGetValue(interfaceType, out generatedProxy))                 {                     generatedProxy = GenerateProxyType(baseType, interfaceType);                     interfaceToProxy[interfaceType] = generatedProxy;                 }                  return generatedProxy;             }         }          // 生成一个派生自'baseType'的新代理类型,并实现'interfaceType'          private static Type GenerateProxyType(Type baseType, Type interfaceType)         {             TypeInfo baseTypeInfo = baseType.GetTypeInfo();              // 接口类型必须是接口,而不是类              if (!interfaceType.GetTypeInfo().IsInterface)             {                 throw new ArgumentException(SR.Format(SR.InterfaceType_Must_Be_Interface, interfaceType.FullName), "T");             }              // 基类型不能密封,因为代理需要将其子类化。              if (baseTypeInfo.IsSealed)             {                 throw new ArgumentException(SR.Format(SR.BaseType_Cannot_Be_Sealed, baseTypeInfo.FullName), "TProxy");             }              // 基类型不能是抽象类型             if (baseTypeInfo.IsAbstract)             {                 throw new ArgumentException(SR.Format(SR.BaseType_Cannot_Be_Abstract, baseType.FullName), "TProxy");             }              // 基类型必须有一个公共默认属性(不然没啥意义)             if (!baseTypeInfo.DeclaredConstructors.Any(c => c.IsPublic && c.GetParameters().Length == 0))             {                 throw new ArgumentException(SR.Format(SR.BaseType_Must_Have_Default_Ctor, baseType.FullName), "TProxy");             }              // 创建baseType类              ProxyBuilder pb = s_proxyAssembly.CreateProxy("generatedProxy", baseType);              // 获取接口中需要实现的信息,动态添加实现             foreach (Type t in interfaceType.GetTypeInfo().ImplementedInterfaces)                 pb.AddInterfaceImpl(t);              // 添加实现             pb.AddInterfaceImpl(interfaceType);              // 实现完接口,创建该类型             Type generatedProxyType = pb.CreateType();             return generatedProxyType;         }          // 调用(抽象的)DispatchProxy.Invoke()方法。          private static void Invoke(object[] args)         {             PackedArgs packed = new PackedArgs(args);             MethodBase method = s_proxyAssembly.ResolveMethodToken(packed.DeclaringType, packed.MethodToken);             // 方法是否泛型方法定义             if (method.IsGenericMethodDefinition)                 // 创建泛型方法定义                 method = ((MethodInfo)method).MakeGenericMethod(packed.GenericTypes);              // 调用(抽象的)DispatchProxy.Invoke()方法             try             {                 Debug.Assert(s_dispatchProxyInvokeMethod != null);                 // 执行packed.DispatchProxy该类方法,获取方法的返回结果                 object returnValue = s_dispatchProxyInvokeMethod.Invoke(packed.DispatchProxy,                                                                        new object[] { method, packed.Args });                 // 执行返回结果                 packed.ReturnValue = returnValue;             }             catch (TargetInvocationException tie)             {                 ExceptionDispatchInfo.Capture(tie.InnerException).Throw();             }         } 

DispatchProxy拓展封装

根据前面的介绍,对DispatchProxy有了一定的了解,我们可以进行一些封装方便以后使用。

DynamicProxy动态代理类

我们创建DynamicProxy类,包装方法执行之前&执行之后的处理,主体方法报错的处理,形成一个动态代理类。

    public class DynamicProxy : DispatchProxy, IScopedDependency     {         private static ILogger<DynamicProxy>? _logger { get; set; }          /// <summary>         /// 目标类         /// </summary>         public object Target { get; set; }          /// <summary>         /// 动作之后执行         /// </summary>         private Action<object?[]?> _afterAction { get; set; }          /// <summary>         /// 动作之前执行         /// </summary>         private Action<object?[]?, object> _beforeAction { get; set; }          /// <summary>         /// 目标方法异常(默认抛出异常信息)         /// </summary>         private Action<MethodInfo?, object?[]?, Exception> _methodExceptionAction { get; set; } = (methodInfo, args, ex) => throw ex;          /// <summary>         /// 执行方法         /// </summary>         /// <param name="targetMethod">目标方法</param>         /// <param name="args">方法参数</param>         /// <returns></returns>         protected override object? Invoke(MethodInfo? targetMethod, object?[]? args)         {             // 异常信息             Exception exception = null;             // 方法执行前处理             AfterAction(args);             // 方法执行结果             object resultValue = null;             if (targetMethod != null)             {                 try                 {                     //调用实际目标对象的方法                     resultValue = targetMethod.Invoke(Target, args);                 }                 catch (Exception ex)                 {                     _logger.LogError($"Invoke=>调用实际目标对象的方法出现错误:{ex.Message},{ex.StackTrace}");                     _methodExceptionAction(targetMethod, args, ex);                 }             }             // 方法执行后处理             BeforeAction(args, resultValue);              // 判断主体方法执行是否异常             if (exception != null)             {                 throw exception;             }              return resultValue;         }          /// <summary>         /// 创建代理实例         /// </summary>         /// <param name="target">代理的接口类型</param>         /// <param name="afterAction">方法执行前执行的事件</param>         /// <param name="beforeAction">方法执行后执行的事件</param>         /// <returns></returns>         public T Create<T>(T target,             Action<object?[]?> afterAction,             Action<object?[]?, object> beforeAction,             Action<MethodInfo?, object?[]?, Exception> targetMethodExceptionAction,             ILogger<DynamicProxy> logger)         {             // DispatchProxy.Create创建T对象             object proxy = Create<T, DynamicProxy>();             _logger = logger;             DynamicProxy proxyDecorator = (DynamicProxy)proxy;             proxyDecorator.Target = target;             proxyDecorator._afterAction = afterAction;             proxyDecorator._beforeAction = beforeAction;             proxyDecorator._methodExceptionAction = targetMethodExceptionAction;             return (T)proxy;         }          private void AfterAction(object?[]? args)         {             if (_afterAction == null)             {                 return;             }              try             {                 _afterAction.Invoke(args);             }             catch (Exception ex)             {                 _logger.LogError($"AfterAction=>执行之前异常:{ex.Message},{ex.StackTrace}");             }         }          private void BeforeAction(object?[]? args, object? result)         {             if (_beforeAction == null)             {                 return;             }              try             {                 _beforeAction.Invoke(args, result);             }             catch (Exception ex)             {                 _logger.LogError($"BeforeAction=>执行之后异常:{ex.Message},{ex.StackTrace}");             }         }     } 

创建IProxyHandle

我们会有很多处理实现类,每个实现类都需要实现AfterActionBeforeActionTargetMethodExceptionAction

   public interface IProxyHandle     {         /// <summary>         /// 执行之前         /// </summary>         /// <param name="args">目标方法参数</param>         void AfterAction(object?[]? args);          /// <summary>         /// 执行之后         /// </summary>         /// <param name="args">目标方法参数</param>         /// <param name="result">目标方法执行结果</param>         void BeforeAction(object?[]? args, object resultValue);          /// <summary>         /// 方法执行错误处理         /// </summary>         /// <param name="targetMethod">目标方法</param>         /// <param name="args">目标方法参数</param>         /// <param name="ex">目标方法执行结果</param>         void MethodExceptionAction(MethodInfo? targetMethod, object?[]? args, Exception ex);     } 

创建ProxyHandleAttribute特性

这里我尝试过几种方式,通过接口或者使用特性,最终特性比较方便团队使用(接口也不错)。

    /// <summary>     /// 代理Aop特性     /// </summary>     [AttributeUsage(AttributeTargets.Class)]     public class ProxyHandleAttribute : Attribute     {         public Type Type { get; set; }         public ProxyHandleAttribute(Type type)         {             this.Type = type;         }     } 

ProxyFactory代理工厂

根据实现类获取Aop切面类型,再获取AOP工厂(IEnumerable<IProxyHandle>)中对应实现。

    /// <summary>     /// 代理工厂     /// </summary>     public class ProxyFactory : IScopedDependency     {         private readonly IServiceProvider _serviceProvider;         private readonly IEnumerable<IProxyHandle> _proxyHandleList;         private readonly DynamicProxy _dynamicProxy;         private readonly ILogger<DynamicProxy> _logger;         public ProxyFactory(IEnumerable<IProxyHandle> proxyHandleList,             IServiceProvider serviceProvider,             DynamicProxy dynamicProxy,             ILogger<DynamicProxy> logger)         {             this._serviceProvider = serviceProvider;             this._proxyHandleList = proxyHandleList;             this._dynamicProxy = dynamicProxy;             this._logger = logger;         }          /// <summary>         /// 创建代理实例         /// </summary>         /// <returns></returns>         public T Create<T>() where T : class         {              var target = _serviceProvider.GetService<T>();             if (target == null)             {                 throw new BusinessException($"执行ProxyFactory=》Create方法:{typeof(T).FullName}未注入");             }             var type = target.GetType();             var proxyHandleAttribute = type.GetCustomAttribute<ProxyHandleAttribute>();             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}");         }     } 
  • 准备ITestServiceTestService
public interface ITestService     {         /// <summary>         /// 获取用户Id信息         /// </summary>         /// <returns></returns>         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/<TestController>         [HttpGet]         public IEnumerable<string> Get()         {             // 从工厂获取代理类             var testService = _proxyFactory.Create<ITestService>();             testService.GetUserId();             return new string[] { "value1", "value2" };         } 

浅析DispatchProxy动态代理AOP

总结

  • DispatchProxy 实现动态代理主要是依赖Emit类库直接编写IL语言。
  • Activator 类在运行时动态构造对象。
  • AssemblyBuilder 类运行时动态一个获取和设置专用字段的属性、初始化专用字段的构造函数,可以动态执行方法并返回结果。

不管是Java还是Net实现AOP切面编程原理差不多。

发表评论

相关文章