动态代理--Spring AOP分析

Spring AOP的基本实现方式

?Spring AOP,一种模块化机制,可以动态的对切点增加行为,而不破坏原有的代码结构。这是一个很好地动态代理的应用方式,Spring AOP实现依赖于JDK的动态代理库和CGLIB字节码库技术两种来分别实现。

?在Spring AOP中,JdkDynamicAopProxy实现基于JDK动态代理生成代理对象,CglibAopProxy来实现基于CGLIB的动态代理对象生成。并通过DefaultAopProxyFactory进行调用,此处采用策略模式,针对不同场景,调用不同的实现。如下我们对具体实现进行分析,如果对SpringAOP有疑惑的话,可以参考如下文章,一篇是我的博客:http://blog.csdn.net/mergades/article/details/46841079 
还有IBM Devloper社区的一篇:http://www.ibm.com/developerworks/cn/java/j-lo-springaopcglib/

DefaultAopProxyFactory

?Spring AOP内部采用AopProxy对使用不同的代理实现机制进行了适度的抽象,针对不同的代理实现机制提供相应的AopProxy子类实现。DefaultAopProxyFactory实现了AopProxyFactory。其中AopProxyFactory接口定义createAopProxy方法,来决定根据哪种具体的策略来实现代理类。具体实现则由DefaultAopProxyFactory实现,我们查看其对应的createAopProxy方法。

?

  1. public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
  2. @Override
  3. public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  4. if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
  5. Class<?> targetClass = config.getTargetClass();
  6. if (targetClass == null) {
  7. throw new AopConfigException("TargetSource cannot determine target class: " +
  8. "Either an interface or a target is required for proxy creation.");
  9. }
  10. if (targetClass.isInterface()) {//如果是接口,则通过JDK的实现,否则通过CGLIB
  11. return new JdkDynamicAopProxy(config);
  12. }
  13. return new ObjenesisCglibAopProxy(config);
  14. }
  15. else {
  16. return new JdkDynamicAopProxy(config);
  17. }
  18. }
  19. /**
  20. * Determine whether the supplied {@link AdvisedSupport} has only the
  21. * {@link org.springframework.aop.SpringProxy} interface specified
  22. * (or no proxy interfaces specified at all).
  23. */
  24. private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
  25. Class<?>[] interfaces = config.getProxiedInterfaces();
  26. return (interfaces.length == 0 || (interfaces.length == 1 && SpringProxy.class.equals(interfaces[0])));
  27. }
  28. }
JdkDynamicAopProxy

?基于JDK动态代理的实现,该类实现了InvocationHandler接口,那么我们根据动态代理的知识可以知道,无论调用目标类的什么方法,都会执行该类的Invoke方法,Invoke方法就是Spring AOP加入切面的主要方法。

?我们查看对应的Invoke方法,虽然Invoke方法整体看起来很长很复杂,但是只要我们包握住几个重点即可了解。

  1. @Override
  2. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  3. MethodInvocation invocation;
  4. Object oldProxy = null;
  5. boolean setProxyContext = false;
  6. //1,获取目标对象。
  7. TargetSource targetSource = this.advised.targetSource;
  8. Class<?> targetClass = null;
  9. Object target = null;
  10. //2,判断对JDK原生方法
  11. try {
  12. if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
  13. // The target does not implement the equals(Object) method itself.
  14. return equals(args[0]);
  15. }
  16. if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
  17. // The target does not implement the hashCode() method itself.
  18. return hashCode();
  19. }
  20. if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
  21. method.getDeclaringClass().isAssignableFrom(Advised.class)) {
  22. // Service invocations on ProxyConfig with the proxy config...
  23. return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
  24. }
  25. Object retVal;
  26. //3,设置代理对象
  27. if (this.advised.exposeProxy) {
  28. // Make invocation available if necessary.
  29. oldProxy = AopContext.setCurrentProxy(proxy);
  30. setProxyContext = true;
  31. }
  32. // May be null. Get as late as possible to minimize the time we "own" the target,
  33. // in case it comes from a pool.
  34. //4,获取目标类
  35. target = targetSource.getTarget();
  36. if (target != null) {
  37. targetClass = target.getClass();
  38. }
  39. // Get the interception chain for this method.
  40. //5,获取通知链
  41. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  42. // Check whether we have any advice. If we don‘t, we can fallback on direct
  43. // reflective invocation of the target, and avoid creating a MethodInvocation.
  44. //6,判断是否存在通知链,并执行对应方法,获取返回值
  45. if (chain.isEmpty()) {
  46. // We can skip creating a MethodInvocation: just invoke the target directly
  47. // Note that the final invoker must be an InvokerInterceptor so we know it does
  48. // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
  49. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
  50. }
  51. else {
  52. // We need to create a method invocation...
  53. invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
  54. // Proceed to the joinpoint through the interceptor chain.
  55. retVal = invocation.proceed();
  56. }
  57. // Massage return value if necessary.
  58. //7,对返回值进行处理
  59. Class<?> returnType = method.getReturnType();
  60. if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
  61. !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
  62. // Special case: it returned "this" and the return type of the method
  63. // is type-compatible. Note that we can‘t help if the target sets
  64. // a reference to itself in another returned object.
  65. retVal = proxy;
  66. } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
  67. throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
  68. }
  69. return retVal;
  70. }
  71. finally {
  72. if (target != null && !targetSource.isStatic()) {
  73. // Must have come from TargetSource.
  74. targetSource.releaseTarget(target);
  75. }
  76. if (setProxyContext) {
  77. // Restore old proxy.
  78. AopContext.setCurrentProxy(oldProxy);
  79. }
  80. }
  81. }

以上是invoke方法的实现,这个方法是动态代理机制较为核心的方法。

下面我们查看在该类中的getProxy方法,查看SpringAOP是如何获取一个代理对象的。

  1. @Override
  2. public Object getProxy(ClassLoader classLoader) {
  3. if (logger.isDebugEnabled()) {
  4. logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
  5. }
  6. //获取代理接口
  7. Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
  8. //获取是否定义equals和hashCode方法
  9. findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  10. //调用JDK Proxy生成代理
  11. return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
  12. }

以上两个方法,我们抛开Spring具体各种细节的实现,完全可以看做是一个简单的动态代理模式的应用。

ObjenesisCglibAopProxy

?ObjenesisCglibAopProxy基于CGLIb的AOP代理对象的生成,在DefaultAopProxyFactory类中,通过调用此方法来实现CGLIB生成代理对象。

  1. @Override
  2. @SuppressWarnings("unchecked")
  3. protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
  4. try {
  5. //具体生成代理,具体实现源码没有公开
  6. Factory factory = (Factory) this.objenesis.newInstance(enhancer.createClass());
  7. factory.setCallbacks(callbacks);
  8. return factory;
  9. }
  10. catch (ObjenesisException ex) {
  11. // Fallback to regular proxy construction on unsupported JVMs
  12. if (logger.isDebugEnabled()) {
  13. logger.debug("Unable to instantiate proxy using Objenesis, falling back to regular proxy construction", ex);
  14. }
  15. return super.createProxyClassAndInstance(enhancer, callbacks);
  16. }
  17. }
总结

?如上的各种实现即为Spring AOP对动态代理的应用,我们通过查看以上代码可以看到动态代理的作用,可以不改变原有代码而动态的加入我们自己的操作,这种方式可以实现对我们代码完全的解耦。

?

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-30 19:42:46

动态代理--Spring AOP分析的相关文章

Java动态代理--&gt;Spring AOP

引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓“登高必自卑,涉远必自迩”.以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系列分别介绍这些Java基础知识,希望对大家有所帮助.): [1] Java反射知识-->Spring IoC :http://www.iteye.com/topic/1123081 [2] Java动态代理-->Spring AOP :http://www.iteye.com/topic/1123293 [3] 属性

动态代理3--Spring AOP分析

Spring AOP的基本实现方式 ?Spring AOP,一种模块化机制,能够动态的对切点添加行为,而不破坏原有的代码结构. 这是一个非常好地动态代理的应用方式.Spring AOP实现依赖于JDK的动态代理库和CGLIB字节码库技术两种来分别实现. ?在Spring AOP中,JdkDynamicAopProxy实现基于JDK动态代理生成代理对象,CglibAopProxy来实现基于CGLIB的动态代理对象生成.并通过DefaultAopProxyFactory进行调用.此处採用策略模式.针

细说Spring——AOP详解(动态代理实现AOP)

前言 嗯,我应该是有一段实现没有写过博客了,在写完了细说Spring——AOP详解(AOP概览)之后,我发现我不知道该怎么写AOP这一部分,所以就把写博客这件事给放下了,但是这件事情又不想就这么放弃,所以今天我仔细思考了一下,决定还是要克服困难,我仔细的想了一下怎么讲解AOP实现这一部分,然后我决定由浅入深的讲解动态代理,然后用动态代理实现一个简单的AOP,感觉这样能够让人对AOP的原理有一个比较深刻的认识,希望能帮到大家.而且最近学习又组建了ACM比赛的队伍,虽然已经要大三了,按理来说应该一心

动态代理实现aop

动态代理实现aop: 1.确定代理对象如接口 2.编写动态代理类,构造器初始化并传入代理对象 3.获得代理对象方法 1).指定代理对象由哪个加载器负责加载 2).指定代理类型 3)当调用代理对象调用其中方法时,该执行哪个方法, 在InvocationHandler h =new InvocationHandler()中 当调用proxy属性或相关方法时,如proxy.toString()会无限循坏,导致内存溢出. 4).3)输出顺序为日志,执行方法.日志,个人感觉用反射的地方蛮多的,没有spri

Java使用动态代理实现AOP

参考资料: http://www.importnew.com/15420.htmlhttp://www.cnblogs.com/techyc/p/3455950.html Spring是借助了动态代理(JDK dynamic proxy)和CGlib两种技术实现AOP的,本文将学习前人的例子使用动态代理模拟AOP的特性. 1. 环境 Java: jdk1.8.0_144 2. 学习动态代理Proxy.newProxyInstance()方法 它的三个参数如下 参数名 类型 说明 loader C

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

在上一节,我们将静态实现AOP,但是对于一个大型项目,要想为每个类,每个方法都去实现AOP ,进行日志记录和权限验证似乎是不可能的. 即使可能对于成百上千个类维护,也是很难维护.所以今天的主题就是如标题所述. (Real Proxy)真正代理和(Dynamic Proxy)动态代理 Real Proxy 类是个抽象类,定义在 System.Runtime.Remoting.Proxies,定义了代理的一些公共的基本的功能方法. Dynamic Proxy 类必须继承Real Proxy,通过重写

Java设计模式-代理模式之动态代理(附源代码分析)

Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代理是在编译的时候就确定了代理类详细类型.假设有多个类须要代理.那么就得创建多个. 另一点,假设Subject中新增了一个方法,那么相应的实现接口的类中也要相应的实现这些方法. 动态代理的做法:在执行时刻.能够动态创建出一个实现了多个接口的代理类.每一个代理类的对象都会关联一个表示内部处理逻辑的Inv

JDK动态代理深入理解分析并手写简易JDK动态代理(上)

原文引用https://www.dazhuanlan.com/2019/08/26/5d6300df6f20f/ 博客真的是好几个月没更了,2019新年第一篇,继续深入动态代理,前两篇简单分析了动态代理的实现原理之后,这次继续深入了解具体的实现方式,并手写一套简易的动态代理已加强理解: 本博客关于Java动态代理相关内容直达链接: JDK动态代理浅析 Cglib动态代理浅析 JDK动态代理深入理解分析并手写简易JDK动态代理(上) JDK动态代理深入理解分析并手写简易JDK动态代理(下) 博客真

【转载】Java JDK 动态代理(AOP)使用及实现原理分析

转自:http://blog.csdn.net/jiankunking/article/details/52143504 版权声明:作者:jiankunking 出处:http://blog.csdn.net/jiankunking 本文版权归作者和CSDN共有 一.什么是代理? 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 代理模式UML图: 简单结构示意图: 为了保持