动态代理3--Spring AOP分析

Posted jzssuanfa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态代理3--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对动态代理的应用。我们通过查看以上代码能够看到动态代理的作用,能够不改变原有代码而动态的增加我们自己的操作。这样的方式能够实现对我们代码全然的解耦。



?









以上是关于动态代理3--Spring AOP分析的主要内容,如果未能解决你的问题,请参考以下文章

JAVA之AOP

Spring两种动态代理原理分析+AOP的坑

aop动态代理源码分析

2020-07-26 带着疑问看源码 -- springboot aop默认采用啥动态代理机制

Android代理模式(静态代理,动态代理,Retrofit代理模式分析)

springAOP源码分析