得到 AopProxy 实例化对象(CglibAopProxy 或 JdkDynamicAopProxy)后,开始创建目标对象的代理对象。

使用JDK动态代理还是CGLIB?

到这里对于到底使用哪种方式的代理可以做一个小总结:

  1. 如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理实现 AOP。
  2. 如果目标对象实现了接口,可以强制使用 CGLIB 实现 AOP。
  3. 如果目标对象没有实现接口,必须采用 CGLIB 库,Spring 会自动在 JDK 动态代理和 CGLIB 之间转换。

强制使用CGLIB代理的方式 <aop:aspectj-autoproxy proxy-target-class="true"/>
JDK 动态代理和 CGLIB 字节码生成的区别?

  1. JDK 动态代理只能对实现了接口的类生成代理,而不能针对类;
  2. CGLIB 是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成 final。

    CglibAopProxy

    获🉐代理对象从 getProxy 方法开始 (接口 AopProxy 定义)
    首先做的事情就是配置 Enhancer 对象,如下所示:

    1. @Override
    2. public Object getProxy(@Nullable ClassLoader classLoader) {
    3. // log
    4. if (logger.isTraceEnabled()) {
    5. logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
    6. }
    7. // 配置 Enhancer 对象
    8. try {
    9. // 获取需要代理的对象的Class对象
    10. Class<?> rootClass = this.advised.getTargetClass();
    11. Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
    12. Class<?> proxySuperClass = rootClass;
    13. // 判断Class是否为cglib生成的Class(会有$$前缀)
    14. if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
    15. // 如果是的话,获取其代理的对象的接口们
    16. proxySuperClass = rootClass.getSuperclass();
    17. Class<?>[] additionalInterfaces = rootClass.getInterfaces();
    18. for (Class<?> additionalInterface : additionalInterfaces) {
    19. this.advised.addInterface(additionalInterface);
    20. }
    21. }
    22. // Validate the class, writing log messages as necessary.
    23. // 验证类的方法是否能代理,不能的话打印下日志
    24. validateClassIfNecessary(proxySuperClass, classLoader);
    25. // Configure CGLIB Enhancer...
    26. Enhancer enhancer = createEnhancer();
    27. if (classLoader != null) {
    28. enhancer.setClassLoader(classLoader);
    29. // 判断是否使用缓存
    30. if (classLoader instanceof SmartClassLoader &&
    31. ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
    32. enhancer.setUseCache(false);
    33. }
    34. }
    35. // 设置代理对象
    36. enhancer.setSuperclass(proxySuperClass);
    37. // 设置代理对象的接口
    38. enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    39. // 代理对象命名规则
    40. enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    41. // 设置类加载器
    42. enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
    43. // 一些回调方法,其中包括我们自定义的增强方法
    44. Callback[] callbacks = getCallbacks(rootClass);
    45. // 回调接口的Class对象
    46. Class<?>[] types = new Class<?>[callbacks.length];
    47. for (int x = 0; x < types.length; x++) {
    48. types[x] = callbacks[x].getClass();
    49. }
    50. // fixedInterceptorMap only populated at this point, after getCallbacks call above
    51. enhancer.setCallbackFilter(new ProxyCallbackFilter(
    52. this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
    53. enhancer.setCallbackTypes(types);
    54. // Generate the proxy class and create a proxy instance.
    55. return createProxyClassAndInstance(enhancer, callbacks);
    56. } catch (CodeGenerationException | IllegalArgumentException ex) {
    57. throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
    58. ": Common causes of this problem include using a final class or a non-visible class", ex);
    59. } catch (Throwable ex) {
    60. // TargetSource.getTarget() failed
    61. throw new AopConfigException("Unexpected AOP exception", ex);
    62. }
    63. }

然后进入方法 createProxyClassAndInstance 创建代理对象。该方法由子类重写完成。
org.springframework.aop.framework.ObjenesisCglibAopProxy#createProxyClassAndInstance

  1. protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
  2. // 代理对象的Class对象
  3. Class<?> proxyClass = enhancer.createClass();
  4. // 代理对象实例
  5. Object proxyInstance = null;
  6. // 尝试使用SpringObjenesis创建对象,不行的话再使用构造方法创建对象
  7. if (objenesis.isWorthTrying()) {
  8. try {
  9. proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
  10. } catch (Throwable ex) {
  11. logger.debug("Unable to instantiate proxy using Objenesis, " +
  12. "falling back to regular proxy construction", ex);
  13. }
  14. }
  15. if (proxyInstance == null) {
  16. // Regular instantiation via default constructor...
  17. try {
  18. Constructor<?> ctor = (this.constructorArgs != null ?
  19. proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
  20. proxyClass.getDeclaredConstructor());
  21. ReflectionUtils.makeAccessible(ctor);
  22. proxyInstance = (this.constructorArgs != null ? ctor.newInstance(this.constructorArgs) : ctor.newInstance());
  23. } catch (Throwable ex) {
  24. throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
  25. "and regular proxy instantiation via default constructor fails as well", ex);
  26. }
  27. }
  28. ((Factory) proxyInstance).setCallbacks(callbacks);
  29. return proxyInstance;
  30. }

JdkDynamicAopProxy

也是从 getProxy 方法开始。
org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)

  1. @Override
  2. public Object getProxy(@Nullable ClassLoader classLoader) {
  3. // log
  4. if (logger.isTraceEnabled()) {
  5. logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
  6. }
  7. // 获得代理对象所有的接口
  8. Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
  9. // 判断接口是否定义了equals和hashcode方法
  10. findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  11. // jdk动态代理创建代理对象
  12. return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
  13. }

JdkDynamicAopProxy 本身就实现了 InvocationHandler 方法,其invoke方法如下:

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