默认情况下,当一个 bean 继承了一个或多个接口的时候,Spring 就会使用 JDK 动态代理

  1. final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
  2. public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
  3. Assert.notNull(config, "AdvisedSupport must not be null");
  4. if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
  5. throw new AopConfigException("No advisors and no TargetSource specified");
  6. }
  7. // advised 就是 ProxyFactory 对象
  8. this.advised = config;
  9. // 获取生成代理对象所需要实现的接口,同时还包括 Spring 自己添加的三个接口:SpringProxy,Advised,DecoratingProxy
  10. this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
  11. // 判断这些方法中有没有定义 equals 和 hashCode 方法
  12. findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
  13. }
  14. @Override
  15. public Object getProxy(@Nullable ClassLoader classLoader) {
  16. if (logger.isTraceEnabled()) {
  17. logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
  18. }
  19. // this.proxiedInterfaces: 获取生成代理对象所需要实现的接口
  20. // this: 就是 JdkDynamicAopProxy,因为 JdkDynamicAopProxy 实现了 InvocationHandler
  21. // 针对所指定的接口生成代理对象,包括用户所添加的接口以及 SpringProxy,Advised,DecoratingProxy
  22. // 所以生成的代理对象可以强制转换为任一个接口类型
  23. return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
  24. }
  25. @Override
  26. @Nullable
  27. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  28. // ...
  29. }
  30. }

1、准备代理

JDK 动态代理除了会添加我们自己的接口外,还会添加三个 Spring 自己的接口:SpringProxy,Advised,DecoratingProxy

  1. public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
  2. Assert.notNull(config, "AdvisedSupport must not be null");
  3. if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
  4. throw new AopConfigException("No advisors and no TargetSource specified");
  5. }
  6. // advised 就是 ProxyFactory 对象
  7. this.advised = config;
  8. // 获取生成代理对象所需要实现的接口,同时还包括 Spring 自己添加的三个接口:SpringProxy,Advised,DecoratingProxy
  9. this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
  10. // 判断这些方法中有没有定义 equals 和 hashCode 方法
  11. findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
  12. }

2、代理类

调用代理逻辑 Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this); 这里的 this 就是 JdkDynamicAopProxy ,因为 JdkDynamicAopProxy 实现了 InvocationHandler 接口

  1. @Override
  2. public Object getProxy(@Nullable ClassLoader classLoader) {
  3. if (logger.isTraceEnabled()) {
  4. logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
  5. }
  6. // this.proxiedInterfaces: 获取生成代理对象所需要实现的接口
  7. // this: 就是 JdkDynamicAopProxy,因为 JdkDynamicAopProxy 实现了 InvocationHandler
  8. // 针对所指定的接口生成代理对象,包括用户所添加的接口以及 SpringProxy,Advised,DecoratingProxy
  9. // 所以生成的代理对象可以强制转换为任一个接口类型
  10. return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
  11. }

3、执行代理逻辑

当代理调用调用某个方法的时候,就会进入 invoke 方法中

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