Skip to content

揭开JDK动态代理和CGLIB代理的神秘面纱

CGLIB动态代理

引入简单的CGLIB例子

在讲解CGLIB动态代理之前,先看一下最简单的CGLIB动态代理的例子。

java
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class EnhancerDemo {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(EnhancerDemo.class);
        enhancer.setCallback(new MethodInterceptorImpl());
        EnhancerDemo demo = (EnhancerDemo) enhancer.create();
        demo.test();
        System.out.println(demo);
    }
    
    public void test() {
        System.out.println("EnhancerDemo test()");
    }
    
    private static class MethodInterceptorImpl implements MethodInterceptor {
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.err.println("Before invoke " + method);
            Object result = methodProxy.invokeSuper(o, objects);
            System.err.println("After invoke" + method);
            return result;
        }
    }
}

运行结果如下:

EnhancerDemo test()
After invokepublic void com.bruis.learnaop.testcglibaop.EnhancerDemo.test()
Before invoke public java.lang.String java.lang.Object.toString()
Before invoke public native int java.lang.Object.hashCode()
After invokepublic native int java.lang.Object.hashCode()
After invokepublic java.lang.String java.lang.Object.toString()
com.bruis.learnaop.testcglibaop.EnhancerDemo$$EnhancerByCGLIB$$413eae0d@53e25b76

可以看到运行结果,除了demo.test()方法之外,System.our.println(demo)也被代理了,首先调用了toString()方法,然后又调用了hashCode,生成的对象为EnhancerDemo的实例,这个类是运行时由CGLIB产生的,Enhancer最关键的步骤就是setCallback()方法来设置拦截器,来拦截代理类的方法。Demo中用到的Enhancer是CGLIB的字节码增强器,用于为无接口的类创建代理proxy,方便对代理类进行拓展,Demo中的代理类就是EnhancerDemo。它的功能与java自带的Proxy类挺相似的,它会根据某个给定的类创建子类,并且非final的方法都带有回调方法。

创建代理对象的几个步骤:

  • 生成代理类的二进制字节码文件
  • 加载二进制字节码,生成Class对象(例如使用Class.forName()方法)
  • 通过反射机制获取实例构造,并创建代理类对象

具体可以查看Enhancer create()源码方法。

深入代理逻辑源码

先用一张流程图来大致浏览下整个CGLIB的代码逻辑 CGLIB的代码逻辑

回到SpringAOP源码。在SpringAOP(下)中,介绍到DefaultAopProxyFactory源码部分

java
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            return new JdkDynamicAopProxy(config);
        } else {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
            } else {
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }
}

从createAopProxy()源码中可以看到,创建SpringAOP有两种方式,一、JDK动态代理;二、CGLIB动态代理;点进ObjenesisCglibAopProxy源码,发现它继承了CglibAopFactory

java
class ObjenesisCglibAopProxy extends CglibAopProxy {
    protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
        // 通过增强器获取代理类的class对象
        Class<?> proxyClass = enhancer.createClass();
        Object proxyInstance = null;
        if (objenesis.isWorthTrying()) {
            try {
                // 创建代理类实例对象
                proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
            } catch (Throwable var7) {
                logger.debug("Unable to instantiate proxy using Objenesis, falling back to regular proxy construction", var7);
            }
        }

        if (proxyInstance == null) {
            try {
                Constructor<?> ctor = this.constructorArgs != null ? proxyClass.getDeclaredConstructor(this.constructorArgTypes) : proxyClass.getDeclaredConstructor();
                ReflectionUtils.makeAccessible(ctor);
                proxyInstance = this.constructorArgs != null ? ctor.newInstance(this.constructorArgs) : ctor.newInstance();
            } catch (Throwable var6) {
                throw new AopConfigException("Unable to instantiate proxy using Objenesis, and regular proxy instantiation via default constructor fails as well", var6);
            }
        }

        // 为代理类实例创建回调方法(拦截器链)
        ((Factory)proxyInstance).setCallbacks(callbacks);
        return proxyInstance;
    }
}

createProxyClassAndInstance方法和前面总结的CGLIB创建代理的步骤一样。

继续查看CglibAopProxy是如何准备Enhancer增强器以及创建拦截器链的。

java
class CglibAopProxy implements AopProxy, Serializable {
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
        }

        try {
            // 获取目标代理类
            Class<?> rootClass = this.advised.getTargetClass();
            Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
            Class<?> proxySuperClass = rootClass;
            int x;
            if (ClassUtils.isCglibProxyClass(rootClass)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                Class[] var5 = additionalInterfaces;
                int var6 = additionalInterfaces.length;

                for(x = 0; x < var6; ++x) {
                    Class<?> additionalInterface = var5[x];
                    this.advised.addInterface(additionalInterface);
                }
            }
            // 验证class
            this.validateClassIfNecessary(proxySuperClass, classLoader);
            // 获取增强器
            Enhancer enhancer = this.createEnhancer();
            // 为Enhancer设置类加载器
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (classLoader instanceof SmartClassLoader && ((SmartClassLoader)classLoader).isClassReloadable(proxySuperClass)) {
                    enhancer.setUseCache(false);
                }
            }

            // 设置代理类,这一步很关键哦。
            enhancer.setSuperclass(proxySuperClass);
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            // 设置strategy策略器
            enhancer.setStrategy(new CglibAopProxy.ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
            Callback[] callbacks = this.getCallbacks(rootClass);
            Class<?>[] types = new Class[callbacks.length];

            for(x = 0; x < types.length; ++x) {
                types[x] = callbacks[x].getClass();
            }
            // 设置回调过滤器
            enhancer.setCallbackFilter(new CglibAopProxy.ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
            enhancer.setCallbackTypes(types);
            // 创建代理类实例,调用子类的createProxyClassAndInstance()方法
            return this.createProxyClassAndInstance(enhancer, callbacks);
        } catch (IllegalArgumentException | CodeGenerationException var9) {
            throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() + ": Common causes of this problem include using a final class or a non-visible class", var9);
        } catch (Throwable var10) {
            throw new AopConfigException("Unexpected AOP exception", var10);
        }
    }
    
    // 获取回调方法
    private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
        // 获取expose-proxy属性设置
        boolean exposeProxy = this.advised.isExposeProxy();
        boolean isFrozen = this.advised.isFrozen();
        boolean isStatic = this.advised.getTargetSource().isStatic();
        // 将aop拦截器封装在DynamicAdvisedInterceptor中
        Callback aopInterceptor = new CglibAopProxy.DynamicAdvisedInterceptor(this.advised);
        Object targetInterceptor;
     
        if (exposeProxy) {
            targetInterceptor = isStatic ? new CglibAopProxy.StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
        } else {
            targetInterceptor = isStatic ? new CglibAopProxy.StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.DynamicUnadvisedInterceptor(this.advised.getTargetSource());
        }

        Callback targetDispatcher = isStatic ? new CglibAopProxy.StaticDispatcher(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.SerializableNoOp();
        // 添加主要的拦截器链
        Callback[] mainCallbacks = new Callback[]{aopInterceptor, (Callback)targetInterceptor, new CglibAopProxy.SerializableNoOp(), (Callback)targetDispatcher, this.advisedDispatcher, new CglibAopProxy.EqualsInterceptor(this.advised), new CglibAopProxy.HashCodeInterceptor(this.advised)};
        Callback[] callbacks;
        if (isStatic && isFrozen) {
            Method[] methods = rootClass.getMethods();
            Callback[] fixedCallbacks = new Callback[methods.length];
            this.fixedInterceptorMap = new HashMap(methods.length);

            for(int x = 0; x < methods.length; ++x) {
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
                fixedCallbacks[x] = new CglibAopProxy.FixedChainStaticTargetInterceptor(chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
                this.fixedInterceptorMap.put(methods[x].toString(), x);
            }

            callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
            System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
            System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
            this.fixedInterceptorOffset = mainCallbacks.length;
        } else {
            callbacks = mainCallbacks;
        }

        return callbacks;
    }
}

拦截器链在CGLIB中扮演者重要角色,从上面源码中看出拦截器被封装为了DynamicAdvisedInterceptor,那么其核心逻辑就应该在DynamicAdvisedInterceptor中,那看看DynamicAdvisedInterceptor都做了哪些事情。

DynamicAdvisedInterceptor都做了些啥工作?

java
    private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
        @Nullable
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            Object oldProxy = null;
            boolean setProxyContext = false;
            Object target = null;
            // 获取要拦截的通知源
            TargetSource targetSource = this.advised.getTargetSource();

            Object var16;
            try {
                if (this.advised.exposeProxy) {
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }

                target = targetSource.getTarget();
                Class<?> targetClass = target != null ? target.getClass() : null;
                // 获取拦截器链,这里的拦截器链是啥?从哪获取拦截器链?
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                Object retVal;
                if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                    // 如果拦截器链为空,则直接进入拦截器链
                    retVal = methodProxy.invoke(target, argsToUse);
                } else {
                    retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();
                }

                retVal = CglibAopProxy.processReturnType(proxy, target, method, retVal);
                var16 = retVal;
            } finally {
                if (target != null && !targetSource.isStatic()) {
                    targetSource.releaseTarget(target);
                }

                if (setProxyContext) {
                    AopContext.setCurrentProxy(oldProxy);
                }

            }

            return var16;
        } 
    }

啥是拦截器链?拦截器链从哪获取?

啥是拦截器链?从哪获取拦截器链?下面继续深入DefaultAdvisorChainFactory方法的getInterceptorsAndDynamicInterceptionAdvice()方法

java
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass) {
        /*
         * 调用DefaultAdvisorAdapterRegistry构造方法获取通知适配器注册器,包括:
         * 1. MethodBeforeAdviceAdapter
         * 2. AfterReturningAdviceAdapter
         * 3. ThrowsAdviceAdapter
         * 
         * Adapter添加进List中的顺序就是上面的顺序。
         * 
         * GlobalAdvisorAdapterRegistry.getInstance()实际上就是去获取DefaultAdvisorAdapterRegistry中的Adapter
         */
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
        // config在这里就是前面所说的ProxyFactory。从ProxyFactory中获取通知
        Advisor[] advisors = config.getAdvisors();
        List<Object> interceptorList = new ArrayList(advisors.length);
        Class<?> actualClass = targetClass != null ? targetClass : method.getDeclaringClass();
        Boolean hasIntroductions = null;
        Advisor[] var9 = advisors;
        int var10 = advisors.length;

        for(int var11 = 0; var11 < var10; ++var11) {
            Advisor advisor = var9[var11];
            // 切面型通知
            if (advisor instanceof PointcutAdvisor) {
                // 将通知强转为切面
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor)advisor;
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    boolean match;
                    if (mm instanceof IntroductionAwareMethodMatcher) {
                        if (hasIntroductions == null) {
                            hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                        }

                        match = ((IntroductionAwareMethodMatcher)mm).matches(method, actualClass, hasIntroductions);
                    } else {
                        match = mm.matches(method, actualClass);
                    }

                    if (match) {
                        /*
                         * 通过通知适配注册器获取方法拦截器,这里返回的是四种拦截器,分别为:
                         * ExposeInvocationInterceptor类型、AspectJAfterAdvice类型、AspectJAroundAdvice类型、MethodBeforeAdviceInterceptor类型
                         * 正好和前面系列文章一、二所描述的四种通知类型一致。
                         */
                        MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                        if (mm.isRuntime()) {
                            MethodInterceptor[] var17 = interceptors;
                            int var18 = interceptors.length;

                            for(int var19 = 0; var19 < var18; ++var19) {
                                MethodInterceptor interceptor = var17[var19];
                                interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                            }
                        } else {
                            interceptorList.addAll(Arrays.asList(interceptors));
                        }
                    }
                }
            } else if (advisor instanceof IntroductionAdvisor) {// 接口型通知
                IntroductionAdvisor ia = (IntroductionAdvisor)advisor;
                if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                    Interceptor[] interceptors = registry.getInterceptors(advisor);
                    interceptorList.addAll(Arrays.asList(interceptors));
                }
            } else {
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }
    
        /*
         * 这里返回的拦截器链为:
         * 1.ExposeInvocationInterceptor
         * 2.AspectJAfterAdvice
         * 3.AspectJAroundAdvice
         * 4.MethodBeforeAdviceInterceptor
         */
        return interceptorList;
    }
}

在DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法中,主要工作是:

  1. 先获取通知适配器注册器
  2. 将注册器包装为可用的拦截器

在这过程中,DefaultAdvisorAdapterRegistry扮演者非常关键的角色。

java
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
    private final List<AdvisorAdapter> adapters = new ArrayList(3);
    
    // 在构造方法里注册前置通知、后置通知和异常通知的适配器,
    public DefaultAdvisorAdapterRegistry() {
        this.registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        this.registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        this.registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }

    // wrap方法在AbstractAutoProxyCreator的buildAdvisors方法中已经讲解到了,用于构建Advisor数组,这里就不再讲解
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
        if (adviceObject instanceof Advisor) {
            return (Advisor)adviceObject;
        } else if (!(adviceObject instanceof Advice)) {
            throw new UnknownAdviceTypeException(adviceObject);
        } else {
            Advice advice = (Advice)adviceObject;
            if (advice instanceof MethodInterceptor) {
                return new DefaultPointcutAdvisor(advice);
            } else {
                Iterator var3 = this.adapters.iterator();

                AdvisorAdapter adapter;
                do {
                    if (!var3.hasNext()) {
                        throw new UnknownAdviceTypeException(advice);
                    }

                    adapter = (AdvisorAdapter)var3.next();
                } while(!adapter.supportsAdvice(advice));

                return new DefaultPointcutAdvisor(advice);
            }
        }
    }

    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
        List<MethodInterceptor> interceptors = new ArrayList(3);
        // 获取通知
        Advice advice = advisor.getAdvice();
        // 判断通知是否是MethodInterceptor类型
        if (advice instanceof MethodInterceptor) {
            interceptors.add((MethodInterceptor)advice);
        }

        Iterator var4 = this.adapters.iterator();

        while(var4.hasNext()) {
            // 将通知强转为AdvisorAdapter类型
            AdvisorAdapter adapter = (AdvisorAdapter)var4.next();
            if (adapter.supportsAdvice(advice)) {
                interceptors.add(adapter.getInterceptor(advisor));
            }
        }

        if (interceptors.isEmpty()) {
            throw new UnknownAdviceTypeException(advisor.getAdvice());
        } else {
            return (MethodInterceptor[])interceptors.toArray(new MethodInterceptor[0]);
        }
    }

    public void registerAdvisorAdapter(AdvisorAdapter adapter) {
        this.adapters.add(adapter);
    }
}

DefaultAdvisorAdapterRegistry类主要负责:

  • 在构造方法里注册前置通知、后置通知和异常通知的适配器
  • 包装Advisor
  • 将Advisor包装为拦截器

既然获取到了拦截器链,那么每个拦截器链都做了些啥呢?回到DynamicAdvisedInterceptor的intercept()方法

调用拦截器链的proceed方法

视线回到DynamicAdvisedInterceptor的intercept方法,在

java
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

执行完成之后,chain中存放好了拦截器链,分别是

  1. ExposeInvocationInterceptor
  2. AspectJAfterAdvice
  3. AspectJAroundAdvice
  4. MethodBeforeAdviceInterceptor
java
    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    Object retVal;
    if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
    // 如果拦截器链为空,则直接进入拦截器链
        retVal = methodProxy.invoke(target, argsToUse);
    } else {
        // 调用拦截器链的proceed方法
        retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();
    }
    retVal = CglibAopProxy.processReturnType(proxy, target, method, retVal);
    var16 = retVal;

后置通知实现逻辑:

java
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable {
    public Object invoke(MethodInvocation mi) throws Throwable {
        Object var2;
        try {
            var2 = mi.proceed();
        } finally {
            this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null);
        }

        return var2;
    }
}
java
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
    
    protected final Object proxy;
    @Nullable
    protected final Object target;
    protected final Method method;
    protected Object[] arguments = new Object[0];
    @Nullable
    private final Class<?> targetClass;
    @Nullable
    private Map<String, Object> userAttributes;
    protected final List<?> interceptorsAndDynamicMethodMatchers;
    private int currentInterceptorIndex = -1;
    
    
    @Nullable
    public Object proceed() throws Throwable {
        
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return this.invokeJoinpoint();
        } else {
            // 获取拦截器链的元素
            Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
            if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
                InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
                Class<?> targetClass = this.targetClass != null ? this.targetClass : this.method.getDeclaringClass();
                return dm.methodMatcher.matches(this.method, targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
            } else {
                return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
            }
        }
    }
}

这里总结下proceed的逻辑:

  1. 根据索引值获取拦截器链中的拦截器
  2. 要么调用拦截器的invoke方法,要么就调用proceed进行下一轮的递归
  3. proceed方法在这里起到了递归的作用

环绕通知实现逻辑:

java
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
    public Object invoke(MethodInvocation mi) throws Throwable {
        if (!(mi instanceof ProxyMethodInvocation)) {
            throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
        } else {
            ProxyMethodInvocation pmi = (ProxyMethodInvocation)mi;
            ProceedingJoinPoint pjp = this.lazyGetProceedingJoinPoint(pmi);
            JoinPointMatch jpm = this.getJoinPointMatch(pmi);
            return this.invokeAdviceMethod(pjp, jpm, (Object)null, (Throwable)null);
        }
    }

    protected ProceedingJoinPoint lazyGetProceedingJoinPoint(ProxyMethodInvocation rmi) {
        return new MethodInvocationProceedingJoinPoint(rmi);
    }
}
java
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, Serializable {
    protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable t) throws Throwable {
        return this.invokeAdviceMethodWithGivenArgs(this.argBinding(jp, jpMatch, returnValue, t));
    }

    protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
        Object[] actualArgs = args;
        if (this.aspectJAdviceMethod.getParameterCount() == 0) {
            actualArgs = null;
        }

        try {
            ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
            return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
        } catch (IllegalArgumentException var4) {
            throw new AopInvocationException("Mismatch on arguments to advice method [" + this.aspectJAdviceMethod + "]; pointcut expression [" + this.pointcut.getPointcutExpression() + "]", var4);
        } catch (InvocationTargetException var5) {
            throw var5.getTargetException();
        }
    }
}

总结下:

  1. AspectJAroundAdvice的invoke方法作用为获取代理方法以及正在处理的切点对象
  2. 将代理方法、切点信息传入AbstractAspectJAdvice的invokeAdviceMethod里进行进一步的参数绑定
  3. invokeAdviceMethodWithGivenArgs方法调用aspectJAdviceMethod.invoke方法,调用AspectJTest类中aroundTest方法

前置通知实现逻辑:

java
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
    private final MethodBeforeAdvice advice;
    
    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        return mi.proceed();
    }
}

public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {
    public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
        this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null);
    }
}

可以注意到:

  1. 代理类的before方法是由AspectJMethodBeforeAdvice类before方法执行的
  2. 在before方法执行完后,调用了MethodInvocation的proceed方法,最终是回到了AspectJAfterAdvice的invoke方法

这整个过程随着AspectJAfterAdvice执行完,整个Demo代码也都走完了。虽然结合着文章开头的时序图,辅以源码来学习整个SpringAOP的运作过程,但也并不能把整个过程描述的非常清楚,下面以本人非常喜欢的一种方式把整个过程展开来。

在这里插入图片描述在这里插入图片描述在这里插入图片描述 以上面这种文本方式,结合着时序图,能够进一步加深对CGLIB源码逻辑的理解。

在这里插入图片描述

JDK动态代理

实例演示

JDK 动态代理的实现主要是借助 InvocationHandler 接口、Proxy 类实现的。在使用时,我们得定义一个位于代理类与委托类之间的中介类,就像传统的微商代理,其实并不是直接跟厂家接触,他们之间可能还会存在一层中介。而这个中介类,需要实现 InvocationHandler 接口:

java
public interface InvocationHandler { 
  Object invoke(Object proxy, Method method, Object[] args);
}
  • proxy:表示程序运行期间生成的代理类对象,后面可以看见使用 Proxy.newProxyInstance()生成
  • method:表示代理对象被调用的方法
  • args:表示代理对象被调用的方法的参数

调用代理对象的每个方法实际最终都是调用 InvocationHandler 的 invoke 方法。后面我们将论证这个结论。

这里我们使用 AgencyHandler 表示中介类,中介类定义为:

java
public class AgencyHandler implements InvocationHandler {

    // 委托类对象
    private Object target;

    public AgencyHandler(){}

    public AgencyHandler(Object target){
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
        long startTime = System.currentTimeMillis();
        // 使用反射执行委托类对象具体方法
        Object result = method.invoke(target, args);
        System.out.println(method.getName() + " cost time is:" + (System.currentTimeMillis() - startTime));
        return result;
    }
}

通过 Proxy 的静态方法 newProxyInstance 生成代理对象:

java
public class Main {

    public static void main(String[] args) {
        AgencyHandler agencyHandler = new AgencyHandler(new Factory());
        // 创建代理对象
        Operator operator = (Operator) Proxy.newProxyInstance(Operator.class.getClassLoader(), 
                            new Class[]{Operator.class}, 
                            agencyHandler);
        operator.sale();
        operator.expand();
    }
}
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
  • loader:表示类加载器,将运行期动态生成的代理类加载到内存
  • interfaces:表示委托类的接口,生成代理类需要实现的接口
  • h:InvocationHandler 实现类对象,负责连接代理类和委托类的中介类

正如预期运行结果为:

txt
sale .... 
sale cost time is:1s
expand .... 
expand cost time is:0s

这里我们将委托类对象 new Factory() 作为 AgencyHandler 构造方法入参创建了 agencyHandler 对象,然后通过 Proxy.newProxyInstance(…) 方法创建了一个代理对象,实际代理类就是这个时候动态生成的。我们调用该代理对象的方法就会调用到 agencyHandler 的 invoke 方法(类似于静态代理),而 invoke 方法实现中调用委托类对象 new Factory() 相应的 method(类似于静态代理)。因此,动态代理内部可以看成是由两组静态代理构成

代理类源码分析

既然 JDK 动态代理的代理对象是运行期生成的,那么它在运行期也会对应一段字节码,可以使用 ProxyGenerator.generateProxyClass 方法进行获取。为了让大家一步到位,这里贴一下这个工具类:

java
public class ProxyUtils {
    public static boolean saveProxyClass(String path, String proxyClassName, Class[] interfaces) {
        if (proxyClassName == null || path == null) {
            return false;
        }
        byte[] classFile = ProxyGenerator.generateProxyClass(proxyClassName, interfaces);
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(path);
            out.write(classFile);
            out.flush();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }
}

将得到的字节码文件进行反编译就能看到其中的源代码了:

java
import com.limynl.proxy.Operator;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements Operator {
  // 这 5 个方法分别是 equals、expand、toString、sale、hashCode
  private static Method m1;
  private static Method m3;
  private static Method m2;
  private static Method m4;
  private static Method m0;

  static {
    try {
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m3 = Class.forName("com.limynl.proxy.Operator").getMethod("expand", new Class[0]);
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      m4 = Class.forName("com.limynl.proxy.Operator").getMethod("sale", new Class[0]);
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      return;
    } catch (NoSuchMethodException noSuchMethodException) {
      throw new NoSuchMethodError(noSuchMethodException.getMessage());
    } catch (ClassNotFoundException classNotFoundException) {
      throw new NoClassDefFoundError(classNotFoundException.getMessage());
    } 
  }
  // 构造方法接收一个 InvocationHandler 对象为参数
  public $Proxy0(InvocationHandler paramInvocationHandler) {
    // 传至父类中的 InvocationHandler 类型变量 h
    super(paramInvocationHandler);
  }

  public final boolean equals(Object paramObject) {
    try {
      // this.h.invoke 将会调用实现了 InvocationHandler 接口的类,上面我们传入的是 agencyHandler 对象,
      // 因此会调用 AgencyHandler 的 invoke 方法
      // 同时这里也印证了,invoke 的方法的第一个参数就是代理对象本身。下面其余方法类似
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }

  public final void expand() {
    try {
      this.h.invoke(this, m3, null);
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }

  public final String toString() {
    try {
      return (String)this.h.invoke(this, m2, null);
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }

  public final void sale() {
    try {
      this.h.invoke(this, m4, null);
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }

  public final int hashCode() {
    try {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
}
  • 从中我们可以看出动态生成的代理类是以 $Proxy 为类名前缀,继承自 Proxy,并且实现了 Proxy.newProxyInstance(…) 第二个参数传入的所有接口。
  • 代理类的构造方法传入的是 InvocationHandler 对象,即 Proxy.newProxyInstance(…) 第三个参数,同时 sale()、expand() 都交给 h 去处理,最终会传递到 agencyHandler 对象的 invoke 方法里面,该方法里面继续使用反射的方式找到最终需要调用的委托类的方法。从而也论证了开头说的:调用代理对象的每个方法实际最终都是调用 InvocationHandler 的 invoke 方法。
  • 所以 InvocationHandler 的子类 AgencyHandler 连接代理类和委托类的中介类。

到这里我们已经把 JDK 动态代理的原理讲完了,所以大家可以在脑海中回忆一下:JDK 动态代理内部可以看成是由两组静态代理构成,是不是这个意思?

通过这个代理类也将明白(这里需要拿笔圈起来^_^):

  • 为什么在 Proxy.newProxyInstance 过程需要接口:因为生成的代理类需要实现这个接口
  • 为什么 JDK 动态代理只能代理接口:因为 java 是单继承,代理类已经继承了 Proxy,因此没办法在继承另外一个类
  • JDK 动态代理中除使用了反射外,也操作了字节码

粤ICP备20009776号