SpringAOP[3]-Cglib代理流程分析


原文:SpringAOP联盟(2)— Cglib代理流程分析 - 简书 (jianshu.com)

1. 在resources目录下加入logback-test.xml的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <springProperty scope="context" name="logPath" source="log.out.path" defalutValue="/app/test.log"/>
    
    
    
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d %p [%r] [%t] [%X{traceRootId}] (%file:%line\): %m%npattern>
            
            <charset>UTF-8charset>
        encoder>
    appender>
    
    <root level="TRACE">
        <appender-ref ref="STDOUT"/>
    root>
    
    
configuration>
@Slf4j
public class Person {
    public void run1() {
        log.info("我在跑步1...");
    }
    public void run2() {
        log.info("我在跑步2...");
    }
}

2. 测试源码:

@Test  
 public void testProxyFactory() {  
     Person person = new Person();  
     //被建议的类,即面向目标类生成代理类  
     ProxyFactory proxyFactory = new ProxyFactory(person);  
     NameMatchMethodPointcut nameMatchMethodPointcut = new NameMatchMethodPointcut();  
     nameMatchMethodPointcut.addMethodName("run1");  
     //通知+切点=advisor  
     DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();  
     advisor.setPointcut(nameMatchMethodPointcut);  
     advisor.setAdvice(new MethodBeforeAdvice() {  
         @Override  
         public void before(Method method, Object[] args, Object target) throws Throwable {  
             System.out.println("before Advice...");  
         }  
     });  
     //加入第二个adsivor  
     NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisor= new NameMatchMethodPointcutAdvisor();  
     nameMatchMethodPointcutAdvisor.addMethodName("run1");  
     nameMatchMethodPointcutAdvisor.setAdvice(new SimpleTraceInterceptor());  
     //第三个advisor  
     NameMatchMethodPointcutAdvisor advisor3= new NameMatchMethodPointcutAdvisor();  
     advisor3.addMethodName("run2");  
     advisor3.setAdvice(new DebugInterceptor());  
     //advisor放入到adviced  
     proxyFactory.addAdvisor(advisor);  
     proxyFactory.addAdvisor(advisor3);  
     proxyFactory.addAdvisor(nameMatchMethodPointcutAdvisor);  
     //最后经过代理生成代理对象  
     Person proxy = (Person) proxyFactory.getProxy();  
     //执行方法  
     proxy.run1();  
 }  

3. 测试结果

before Advice...
2021-11-16 11:34:59.859 [main] TRACE o.s.aop.interceptor.SimpleTraceInterceptor - Entering method 'run1' of class [cn.lemon.spring.demo.pojo.Person]
2021-11-16 11:34:59.865 [main] INFO cn.lemon.spring.demo.pojo.Person - 我在跑步1...
2021-11-16 11:34:59.865 [main] TRACE o.s.aop.interceptor.SimpleTraceInterceptor - Exiting method 'run1' of class [cn.lemon.spring.demo.pojo.Person]

流程解析

1. 将advisor交由advised管理

  • advisor:增强器(由advice和pointcut组成)
  • advised:代理对象配置类(代理对象的配置以及所有的advisor)

继承AdvisedSupportProxyFactory负责创建代理对象,创建出来的代理对象不仅保存了target对象,也保存了Advised所有Advisor)对象、ProxyConfig(代理对象的配置)对象。

 

AdvisedSupport实现了Advised接口大部分的方法。

 

AdvisorAdvice+Pointcut组成(通知 + 切入点),可以称为一个增强器,而ProxyFactory管理着所有的Advisor,根据Pointcut(切入点)配置决定为目标对象的方法增加拦截。

调用ProxyFactoryaddAdvisor实际上的是AdvisedSupport实现的addAdvisor

public class AdvisedSupport extends ProxyConfig implements Advised {
    // 实现的 Advised 接口的方法, 添加一个 Advisor
    @Override
    public void addAdvice(Advice advice) throws AopConfigException {
        int pos = this.advisors.size();
        addAdvice(pos, advice);
    }
    
    // ?
    public void addAdvice(int pos, Advice advice) throws AopConfigException {
        if (advice instanceof IntroductionInfo) {
            // We don't need an IntroductionAdvisor for this kind of introduction:
            // It's fully self-describing.
            addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
        }
        else if (advice instanceof DynamicIntroductionAdvice) {
            // We need an IntroductionAdvisor for this kind of introduction.
            throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
        }
        else {
            addAdvisor(pos, new DefaultPointcutAdvisor(advice));
        }
    }
    /**
     * 添加一个 Advisor
     * @param pos 在 chain 中的位置, 0 为头部 head position in chain (0 is head). Must be valid.
     */
    @Override
    public void addAdvisor(int pos, Advisor advisor) throws AopConfigException {
        if (advisor instanceof IntroductionAdvisor) {
            validateIntroductionAdvisor((IntroductionAdvisor) advisor);
        }
        addAdvisorInternal(pos, advisor);
    }
    
    private void addAdvisorInternal(int pos, Advisor advisor) throws AopConfigException {
        Assert.notNull(advisor, "Advisor must not be null");
        // 配置不能再改变了
        if (isFrozen()) {
            throw new AopConfigException("Cannot add advisor: Configuration is frozen.");
        }
        if (pos > this.advisors.size()) {
            throw new IllegalArgumentException(
                    "Illegal position " + pos + " in advisor list with size " + this.advisors.size());
        }
        // List advisors, 链表
        this.advisors.add(pos, advisor);
        // this.methodCache.clear() 缓存清空
        adviceChanged();
    }
}

2. 创建出代理对象

源码位置:org.springframework.aop.framework.CglibAopProxy#getProxy

由上图所知,即使不存在advisorgetProxy()依旧生成了一个代理对象。

ProxyFactory的作用是将targetadviced中的所有advisors整合在一起,生成proxy对象。待执行具体方法进行拦截。


3. 拦截方法

 

当调用代理对象的run1()方法后,实际上执行的是DynamicAdvisedInterceptor接口(CglibAopProxy内部类)的intercept()方法。

(1)首先获取到对应Method方法上的chain(拦截器链)。

(2)递归执行拦截方法+目标方法。

代理对象的运行:

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();  
    try {  
        //若是设置了exposeProxy=true属性,便可以在同一线程中获取代理对象
        if (this.advised.exposeProxy) {  
            oldProxy = AopContext.setCurrentProxy(proxy);  
            setProxyContext = true;  
        }  
        //获取到目标对象
        target = targetSource.getTarget();  
        Class<?> targetClass = (target != null ? target.getClass() : null);  
        //(重点关注)1. 获取advised的该方法上的过滤器链
        List 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 {  
           //(重点关注)2. 开始执行方法的回调
            retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();  
        }  
        retVal = processReturnType(proxy, target, method, retVal);  
        return retVal;  
    }  
    finally {  
        if (target != null && !targetSource.isStatic()) {  
            targetSource.releaseTarget(target);  
        }  
        if (setProxyContext) {  
            // Restore old proxy.  
            AopContext.setCurrentProxy(oldProxy);  
        }  
    }  
}  


3.1 获取过滤器链

依旧是AdvicedSupport,代理对象配置类的方法,作用是获取方法上的拦截器链。

addAdvisorInternal方法中,最后执行的adviceChanged()方法,实际上是调用methodCache.clear()方法,即清空拦截器缓存List。

注意:MethodCacheKey是由Method实例 + method.hashCode()组成,确保key的唯一性。

public List getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {  
    MethodCacheKey cacheKey = new MethodCacheKey(method);  
    //每次加入advisor后均清空methodCache,于是需要重新的生成cached
    List cached = this.methodCache.get(cacheKey);  
    if (cached == null) {  
        cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(  
                this, method, targetClass);  
        this.methodCache.put(cacheKey, cached);  
    }  
    return cached;  
}  

而实际上获取AdvisorChain的方法是AdvisorChainFactory接口实现的。

 

该方法作用有两个,

  1. 遍历所有的Advisor,若可以切入该方法(根据Pointcut配置决定),执行步骤2;
  2. Advisor解析为MethodInterceptor[]对象,并加入到List interceptorList中。
    public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
    
        @Override
        public List getInterceptorsAndDynamicInterceptionAdvice(
                Advised config, Method method, @Nullable Class<?> targetClass) {
    
            // This is somewhat tricky... We have to process introductions first,
            // but we need to preserve order in the ultimate list.
            // 饿汉式单例,最终生成DefaultAdvisorAdapterRegistry对象
            AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
            // 入参配置中获取所有 Advisor 
            Advisor[] advisors = config.getAdvisors();
            List interceptorList = new ArrayList<>(advisors.length);
            // 获取声明 method 的实际类型, 也就是目标对象的类型
            Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
            Boolean hasIntroductions = null;
    
            for (Advisor advisor : advisors) {
                // 两种 Advisor, PointcutAdvisor 和 IntroductionAdvisor
                // PointcutAdvisor#getPointcut 直接能获得切入点[AspectJPointcutAdvisor]
                // IntroductionAdvisor#getClassFilter[DefaultIntroductionAdvisor]
                if (advisor instanceof PointcutAdvisor) {
                    PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                    // ? || Class是否满足被拦截条件
                    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) {
                            // 将advisor中的内容转化为MethodInterceptor
                            MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                            // MethodMatcher 是否为动态的, 也就是在运行期间是否匹配可能改变, 那么就需要每次invoke运行时再判断一次是否匹配
                            if (mm.isRuntime()) {
                                for (MethodInterceptor interceptor : interceptors) {
                                    // MethodInterceptors 和 MethodMatcher 的封装, DynamicMethodMatcher - 动态方法匹配
                                    interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                                }
                            }
                            else {
                                // 直接添加
                                interceptorList.addAll(Arrays.asList(interceptors));
                            }
                        }
                    }
                }
                else if (advisor instanceof IntroductionAdvisor) {
                    IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                    // Class 匹配即可?
                    if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                        // 将advisor中的内容转化为MethodInterceptor
                        Interceptor[] interceptors = registry.getInterceptors(advisor);
                        // 直接添加, 没有动态的判断
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
                else {
                    Interceptor[] interceptors = registry.getInterceptors(advisor);
                    interceptorList.addAll(Arrays.asList(interceptors));
                }
            }
    
            return interceptorList;
        }
    }
    
    
    
    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();生成的注册器。该类的主要作用是将Advice解析为MethodInterceptor对象。
    
    
    
    
    public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
        private final List adapters = new ArrayList<>(3);
        /**
         * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
         */
        public DefaultAdvisorAdapterRegistry() {
            registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
            registerAdvisorAdapter(new AfterReturningAdviceAdapter());
            registerAdvisorAdapter(new ThrowsAdviceAdapter());
        }
        @Override
        public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
            List interceptors = new ArrayList<>(3);
            Advice advice = advisor.getAdvice();
            //若是Advice实现了MethodInterceptor接口,直接加入到List中
            if (advice instanceof MethodInterceptor) {
                interceptors.add((MethodInterceptor) advice);
            }
            for (AdvisorAdapter adapter : this.adapters) {
              //若是advice实现了MethodBeforeAdvice等类型,则转换为MethodInterceptor,注意这些方法由子类实现。
                if (adapter.supportsAdvice(advice)) {
                    interceptors.add(adapter.getInterceptor(advisor));
                }
            }
            if (interceptors.isEmpty()) {
                throw new UnknownAdviceTypeException(advisor.getAdvice());
            }
            return interceptors.toArray(new MethodInterceptor[0]);
        }
    }

    3.2 递归执行方法

    retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
    注意在这里每次调用都new,意味着下面的 ReflectiveMethodInvocation 每次状态都是重置的(currentInterceptorIndex)
    class CglibAopProxy implements AopProxy, Serializable {
        private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
            public Object proceed() throws Throwable {
                try {
                    return super.proceed();
                }
            }
        }
    }
    
    public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
        // Joinpoint 接口实现, 连接点
        @Override
        @Nullable
        public Object proceed() throws Throwable {
            // We start with an index of -1 and increment early.
            // 默认-1, 后者实际是 List, 不要被名称迷惑了
            if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
                // 所有拦截器已经调用完毕了, 则反射调用其 target 的方法
                return invokeJoinpoint();
            }
            
            // 获取第一个拦截器
            Object interceptorOrInterceptionAdvice =
                    this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
            // 动态 Matcher 则再次判断是否匹配
            if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
                // Evaluate dynamic method matcher here: static part will already have
                // been evaluated and found to match.
                InterceptorAndDynamicMethodMatcher dm =
                        (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
                Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
                if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                    // 匹配则调用拦截, 注意传入了this(参数声明类型 MethodInvocation)
                    // this 也是一个 ProxyMethodInvocation(MethodInvocation), 每个 interceptor 都会调用 MethodInvocation#proceed, 类似递归调用
                    return dm.interceptor.invoke(this);
                }
                else {
                    // Dynamic matching failed.
                    // Skip this interceptor and invoke the next in the chain.
                    // 不匹配则递归调用, 执行下一个拦截点
                    return proceed();
                }
            }
            else {
                // It's an interceptor, so we just invoke it: The pointcut will have
                // been evaluated statically before this object was constructed.
                // 其他的直接调用, 注意传入了this(参数声明类型 MethodInvocation)
                return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
            }
        }
    }
    
    
    

    拦截器回调方法:org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor#invoke

    @Override  
    public Object invoke(MethodInvocation mi) throws Throwable {  
        //因为Advice被转换成为了MethodInterceptor对象,包装了invoke方法
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());  
        //继续执行(JoinPoint)后续的方法,即递归调用。
        return mi.proceed();  
    }  

     

    递归出口——执行Joinpoint方法:org.springframework.aop.framework.CglibAopProxy.CglibMethodInvocation#invokeJoinpoint
    @Override  
    protected Object invokeJoinpoint() throws Throwable {  
        if (this.methodProxy != null) {  
            //回调方法
            return this.methodProxy.invoke(this.target, this.arguments);  
        }  
        else {  
            return super.invokeJoinpoint();  
        }  
    }  

    实际上执行的是:org.springframework.cglib.proxy.MethodProxy#invoke

    class CglibAopProxy implements AopProxy, Serializable {
        private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
            @Override
            protected Object invokeJoinpoint() throws Throwable {
                if (this.methodProxy != null) {
                    //  一般是这个
                    return this.methodProxy.invoke(this.target, this.arguments);
                }
                else {
                    // 父类就是直接反射调用 target 的方法
                    return super.invokeJoinpoint();
                }
            }
        }
    }
    
    public class MethodProxy {
        public Object invoke(Object obj, Object[] args) throws Throwable {
            try {
                // 初始化 FastClass 封装便于快速调用
                init();
                FastClassInfo fci = fastClassInfo;
                // 上面init初始化的, f1是target类, f2是proxy类型, i1是target的方法, i2是proxy代理后方法, obj 为 target 实例
                return fci.f1.invoke(fci.i1, obj, args);
            }
        }
    }

    Cglib详解...指出了生成一个Cglib的Proxy对象,实际上会生成3个文件,在Java代码中表示:??

    • f1表示的是代理类的FastClass对象;
    • f2表示目标类的FastClass对象
    • i1表示run1()方法的下标(代理对象run1()会经过拦截)。
    • i2表示CGLIB$run1$0方法的下标(代理对象中该方法是super.run1())。
    会有上述特点的原因是:(1)Cglib采用FastClass方法回调方法。(2)Cglib代理对象是目标对象的子类,故super.run1()执行的是目标对象的run1()方法。

    fci.f1.invoke(fci.i1, obj, args)含义是,在代理类的FastClass对象中执行run1()方法,而参数obj对象去执行run1()方法。而此处obj对象是target对象。

    即递归出口中最终执行的是targetrun1(),且结束调用。