zoukankan      html  css  js  c++  java
  • SpringAOP理解-代理对象创建(七)

      SpringAOP的核心首先是创建代理对象存入SpringIoC容器中,然后就是调用的时候使用责任链模式进行调用。首先研究SpringAOP创建代理对象的机制。

      在Spring的AOP实现中,使用的核心技术是代理技术,而这种动态代理实际上是JDK的一个特性(1.3)。基于JDK动态代理的target目标对象必须实现接口。如果没有实现的接口需要基于Cglib代理。当然可以使用@EnableAspectJAutoProxy(proxyTargetClass  = true) 强转使用Cglib代理。

      在Java社区里AspectJ是最完整的AOP框架,但SpringAOP也提供了另外一种实现,这种实现并不是AspectJ的竞争者,相反,SpringAOP还将AspectJ集成了进来,为IoC容器和Spring应用开发提供了一个一致性的AOP解决方案。

      SpringAOP的核心技术是代理技术。以动态代理技术为基础,设计出了一系列AOP的横切实现,比如前置通知、返回通知、异常通知等。同时,SpringAOP还提供了一系列的Pointcut来匹配切入点,可以使用现有的切入点来设计横切面,也可以扩展相应的Pointcut来实现切入需求。(我们可以看到好多aspectj包相关的东西,其实Spring只是引用了AspectJ的语法,其实现核心还是基于代理以及责任链模式来实现代理链条调用)。

      在SpringAOP中,对于AOP的使用者来说,只需要配置相关的bean。但是为了能让AOP起作用,需要完成一系列的过程,比如:为目标对象建立代理对象,这个代理对象可以用JDK代理,也可以用CGLIB代理;然后还需要启动代理对象的拦截器来完成切面的织入,这一系列的织入设计是通过一系列Adapter来实现的。通过Adapter的设计,可以把AOP的横切面设计和Proxy模式有机地结合起来,从而实现在AOP中定义好的各种织入方式。

    1. 代理测试

    1. jdk动态代理测试:

    接口:

    package proxy;
    
    public interface UserDao {
    
        String method1();
    }

    实现类:

    package cn.qz.proxy;
    
    public class UserDaoImpl implements UserDao {
        @Override
        public String method1() {
            System.out.println("cn.qz.proxy.UserDaoImpl.method1====");
            return "method1";
        }
    }

    测试代理:

    package cn.qz.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class Client {
    
        public static void main(String[] args) {
            final UserDao target = new UserDaoImpl();
            UserDao o = (UserDao) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
                /**
                 * @author
                 * @date 2021/2/23 18:56
                 * @param proxy:    代理对象
                 * @param method:   反射方法对象
                 * @param args: 参数列表
                 */
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("方法执行前");
                    //运用反射执行目标对象方法
                    Object returnValue = method.invoke(target, args);
                    System.out.println("方法执行后");
                    return returnValue;
                }
            });
            String s = o.method1();
            System.out.println(s);
        }
    }

    结果:

    方法执行前
    cn.qz.proxy.UserDaoImpl.method1====
    方法执行后
    method1

    2. cglib代理测试

      cglib的流程大体是创Enhancer对象,然后设置其父类,设置回调(回调是个Callback对象,也可以传递数组。实际net.sf.cglib.proxy.MethodInterceptor 继承自Callback接口)。单个Callback不需要传递设置CallbackFilter,多个Callback需要设置CallbackFilter( 内部accept方法返回Cabblack数组的下标),让Cglib知道获取Callback的规则。

    0. pom:

            <!-- https://mvnrepository.com/artifact/cglib/cglib -->
            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>3.2.12</version>
            </dependency>

    1. 单个Callback的测试:

    代理类:

    package cn.qz.proxy;
    
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    public class CglibMethodInterceptor1 implements MethodInterceptor {
    
        /**
         * 1、代理对象;2、委托类方法;3、方法参数;4、代理方法的MethodProxy对象。
         *
         * @param o
         * @param method
         * @param objects
         * @param methodProxy
         * @return
         * @throws Throwable
         */
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("CglibMethodInterceptor1 start......" + method.getName());
            Object o1 = methodProxy.invokeSuper(o, objects);
            System.out.println("CglibMethodInterceptor1 end......." + method.getName());
            return o1;
        }
    }

    测试类:

        public static void main(String[] args) {
            //在指定目录下生成动态代理类,我们可以反编译看一下里面到底是一些什么东西
            System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "G:/proxy");
    
            CglibMethodInterceptor1 methodInterceptor1 = new CglibMethodInterceptor1();//jdk需要提供接口,cglib需要是非私有类,且不能处理final关键字修饰的方法
            Enhancer enhancer = new Enhancer();
            //设置父类
            enhancer.setSuperclass(UserDaoImpl.class);
            //设置回调对象
            enhancer.setCallback(methodInterceptor1);
    
            UserDaoImpl proxy = (UserDaoImpl) enhancer.create();
            proxy.method1();
        }

    结果:

    CglibMethodInterceptor1 start......method1
    cn.qz.proxy.UserDaoImpl.method1====
    CglibMethodInterceptor1 end.......method1

    2. 多个Callback的测试

    接口:

    package cn.qz.proxy;
    
    public interface UserDao {
    
        String method1();
    
        String method2();
    }

    实现类:

    package cn.qz.proxy;
    
    public class UserDaoImpl implements UserDao {
        @Override
        public String method1() {
            System.out.println("cn.qz.proxy.UserDaoImpl.method1====");
            return "method1";
        }
    
        @Override
        public String method2() {
            System.out.println("cn.qz.proxy.UserDaoImpl.method2====");
            return "method2";
        }
    }

    增加Callback2

    package cn.qz.proxy;
    
    import net.sf.cglib.proxy.MethodInterceptor;
    
    import java.lang.reflect.Method;
    
    public class CglibMethodInterceptor2 implements MethodInterceptor {
    
        /**
         * 1、代理对象;2、委托类方法;3、方法参数;4、代理方法的MethodProxy对象。
         *
         * @param o
         * @param method
         * @param objects
         * @param methodProxy
         * @return
         * @throws Throwable
         */
        @Override
        public Object intercept(Object o, Method method, Object[] objects, net.sf.cglib.proxy.MethodProxy methodProxy) throws Throwable {
            System.out.println("CglibMethodInterceptor2 start......" + method.getName());
            Object o1 = methodProxy.invokeSuper(o, objects);
            System.out.println("CglibMethodInterceptor2 end......." + method.getName());
            return o1;
        }
    }

    测试:

    package cn.qz.proxy;
    
    import net.sf.cglib.core.DebuggingClassWriter;
    import net.sf.cglib.proxy.Callback;
    import net.sf.cglib.proxy.CallbackFilter;
    import net.sf.cglib.proxy.Enhancer;
    
    import java.lang.reflect.Method;
    
    public class CglibClient {
    
        public static void main(String[] args) {
            //在指定目录下生成动态代理类,我们可以反编译看一下里面到底是一些什么东西
            System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "G:/proxy");
    
            CglibMethodInterceptor1 methodInterceptor1 = new CglibMethodInterceptor1();
            CglibMethodInterceptor2 methodInterceptor2 = new CglibMethodInterceptor2();
            //jdk需要提供接口,cglib需要是非私有类,且不能处理final关键字修饰的方法
            Enhancer enhancer = new Enhancer();
            //设置父类
            enhancer.setSuperclass(UserDaoImpl.class);
            //设置回调对象
            enhancer.setCallbacks(new Callback[]{methodInterceptor1, methodInterceptor2});
            // 设置CallbackFilter
            enhancer.setCallbackFilter(new CallbackFilter() {
                @Override
                public int accept(Method method) {
                    String name = method.getName();
                    if ("method1".equals(name)) {
                        return 0;
                    }
                    return 1;
                }
            });
    
            UserDaoImpl proxy = (UserDaoImpl) enhancer.create();
            proxy.method1();
            proxy.method2();
        }
    }

    结果:

    CglibMethodInterceptor1 start......method1
    cn.qz.proxy.UserDaoImpl.method1====
    CglibMethodInterceptor1 end.......method1
    CglibMethodInterceptor2 start......method2
    cn.qz.proxy.UserDaoImpl.method2====
    CglibMethodInterceptor2 end.......method2

    2. 测试Spring代理对象

      简单测试Aop代理生成的类的class信息

    1. pom

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>cn.qz</groupId>
        <artifactId>springlearn</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.1.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
        <name>springlearn</name>
        <!-- FIXME change it to the project's website -->
        <url>http://www.example.com</url>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.7</maven.compiler.source>
            <maven.compiler.target>1.7</maven.compiler.target>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
    
            <!-- 引入 spring aop 依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
                <plugins>
                    <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
                    <plugin>
                        <artifactId>maven-clean-plugin</artifactId>
                        <version>3.1.0</version>
                    </plugin>
                    <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                    <plugin>
                        <artifactId>maven-resources-plugin</artifactId>
                        <version>3.0.2</version>
                    </plugin>
                    <plugin>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <version>3.8.0</version>
                    </plugin>
                    <plugin>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <version>2.22.1</version>
                    </plugin>
                    <plugin>
                        <artifactId>maven-jar-plugin</artifactId>
                        <version>3.0.2</version>
                    </plugin>
                    <plugin>
                        <artifactId>maven-install-plugin</artifactId>
                        <version>2.5.2</version>
                    </plugin>
                    <plugin>
                        <artifactId>maven-deploy-plugin</artifactId>
                        <version>2.8.2</version>
                    </plugin>
                    <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
                    <plugin>
                        <artifactId>maven-site-plugin</artifactId>
                        <version>3.7.1</version>
                    </plugin>
                    <plugin>
                        <artifactId>maven-project-info-reports-plugin</artifactId>
                        <version>3.0.0</version>
                    </plugin>
                </plugins>
            </pluginManagement>
        </build>
    </project>

    2. 类信息

    主类

    package cn.qz;
    
    import cn.qz.user.DeptDao;
    import cn.qz.user.UserDao;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    
    @ComponentScan
    @EnableAspectJAutoProxy
    public class App {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(App.class);
            UserDao bean = applicationContext.getBean(UserDao.class);
            System.out.println(bean.getClass());
            DeptDao bean1 = applicationContext.getBean(DeptDao.class);
            System.out.println(bean1.getClass());
        }
    }

    Aop类

    package cn.qz.aop;
    
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    import java.util.Arrays;
    
    @Aspect // 表示该类是一个通知类
    @Component // 交给spring管理
    public class MyAdvice {
    
        // 定义一个空方法,借用其注解抽取切点表达式
        @Pointcut("execution(* cn.qz..*.*(..))")
        public void pc() {
        }
    
        // 前置通知
        @Before("MyAdvice.pc()")
        public void before(JoinPoint joinPoint) throws Exception {
            System.out.println("---------------前置通知开始~~~~~~~~~~~");
            // 获取到类名
            String targetName = joinPoint.getTarget().getClass().getName();
            System.out.println("代理的类是:" + targetName);
            // 获取到方法名
            String methodName = joinPoint.getSignature().getName();
            System.out.println("增强的方法是:" + methodName);
            // 获取到参数
            Object[] parameter = joinPoint.getArgs();
            System.out.println("传入的参数是:" + Arrays.toString(parameter));
            // 获取字节码对象
            Class<?> targetClass = Class.forName(targetName);
            // 获取所有的方法
            Method[] methods = targetClass.getMethods();
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class[] clazzs = method.getParameterTypes();
                    if (clazzs.length == parameter.length) {
                        System.out.println("找到这个方法");
                        //处理一些业务逻辑
                        break;
                    }
                }
            }
            System.out.println("---------------前置通知结束~~~~~~~~~~~");
        }
    
        // 后置通知(异常发生后不会调用)
        @AfterReturning("MyAdvice.pc()")
        public void afterRunning() {
            System.out.println("这是后置通知(异常发生后不会调用)");
        }
    
        // 环绕通知(推荐下面这种方式获取方法)
        @Around("MyAdvice.pc()")
        public Object around(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println("----------------环绕通知之前 的部分----------------");
            // 获取到类名
            String targetName = pjp.getTarget().getClass().getName();
            System.out.println("代理的类是:" + targetName);
            // 获取到参数
            Object[] parameter = pjp.getArgs();
            System.out.println("传入的参数是:" + Arrays.toString(parameter));
            // 获取到方法签名,进而获得方法
            MethodSignature signature = (MethodSignature) pjp.getSignature();
            Method method = signature.getMethod();
            System.out.println("增强的方法名字是:" + method.getName());
            //处理一些业务逻辑
    
    
            // 获取参数类型
            Class<?>[] parameterTypes = method.getParameterTypes();
            System.out.println("参数类型是:" + parameterTypes.toString());
    
            //让方法执行(proceed是方法的返回结果,可以针对返回结果处理一下事情)
            System.out.println("--------------方法开始执行-----------------");
            Object proceed = pjp.proceed();
    
            //环绕通知之后的业务逻辑部分
            System.out.println("----------------环绕通知之后的部分----------------");
            return proceed;
        }
    
        // 异常通知
        @AfterThrowing("MyAdvice.pc()")
        public void afterException() {
            System.out.println("这是异常通知(发生异常后调用)~~~~~~~~~~~");
        }
    
        // 最终通知(发生异常也会在最终调用)
        @After("MyAdvice.pc()")
        public void after() {
            System.out.println("这是后置通知(发生异常也会在最终调用)");
        }
    }

    测试类:

    UserDao

    package cn.qz.user;
    
    public interface UserDao {
    
        void addUser();
    }

    UserDaoImpl

    package cn.qz.user;
    
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserDaoImpl implements  UserDao{
        @Override
        public void addUser() {
            System.out.println("addUser");
        }
    }

    DeptDao

    package cn.qz.user;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class DeptDao {
    
        public void test(){
            System.out.println("test");
        }
    }

    启动后测试结果如下:

    class com.sun.proxy.$Proxy22
    class cn.qz.user.DeptDao$$EnhancerBySpringCGLIB$$fb860d23

      上面也证实了有接口是基于JDK的动态代理,没有实现接口是基于CGLIB的继承代理。

    3.创建代理代码跟踪

      在IoC中研究中,大致了解到对象的创建过程,且了解到BeanPostProcessor在对象创建过程中的调用过程以及调用时机。

    1. org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean 对象初始化过程如下:

        protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }, getAccessControlContext());
            }
            else {
                invokeAwareMethods(beanName, bean);
            }
    
            Object wrappedBean = bean;
            if (mbd == null || !mbd.isSynthetic()) {
                wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
            }
    
            try {
                invokeInitMethods(beanName, wrappedBean, mbd);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(
                        (mbd != null ? mbd.getResourceDescription() : null),
                        beanName, "Invocation of init method failed", ex);
            }
            if (mbd == null || !mbd.isSynthetic()) {
                wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
            }
    
            return wrappedBean;
        }

    2. 上面代码中在调用 invokeInitMethods 初始化方法之后会调用applyBeanPostProcessorsAfterInitialization  

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization 源码如下:

        public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
                throws BeansException {
    
            Object result = existingBean;
            for (BeanPostProcessor processor : getBeanPostProcessors()) {
                Object current = processor.postProcessAfterInitialization(result, beanName);
                if (current == null) {
                    return result;
                }
                result = current;
            }
            return result;
        }

    其实代理对象的创建也是在这个过程中,中发生的。debug查看getBeanPostProcessors() 的返回结果如下:

    可以猜测进行代理对象的创建是在 AnnotationAwareAspectJAutoProxyCreator 类中,AnnotationAwareAspectJAutoProxyCreator类继承自的方法,org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization源码如下:

        public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
            if (bean != null) {
                Object cacheKey = getCacheKey(bean.getClass(), beanName);
                if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                    return wrapIfNecessary(bean, beanName, cacheKey);
                }
            }
            return bean;
        }

    这个方法内部通过处理后返回代理对象的引用。

    3. org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary 源码如下;

        protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
            if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
                return bean;
            }
            if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
                return bean;
            }
            if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
            }
    
            // Create proxy if we have advice.
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
            if (specificInterceptors != DO_NOT_PROXY) {
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                Object proxy = createProxy(
                        bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            }
    
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

    (1) Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); 这一行代码返回 该对象的Advice和Advisor,也就是通知相关对象,debug查看返回的结果如下:

       实际上也是AOP调用链的数组,第一个ExposeInvocationInterceptor 是Spring内置的一个通知,在AOP调用链过程中起作用。

    再次查看Advisor解析过程:

    1》org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean  获取结果

        protected Object[] getAdvicesAndAdvisorsForBean(
                Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
    
            List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
            if (advisors.isEmpty()) {
                return DO_NOT_PROXY;
            }
            return advisors.toArray();
        }

    2》接着调用org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors 

        protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
            List<Advisor> candidateAdvisors = findCandidateAdvisors();
            List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
            extendAdvisors(eligibleAdvisors);
            if (!eligibleAdvisors.isEmpty()) {
                eligibleAdvisors = sortAdvisors(eligibleAdvisors);
            }
            return eligibleAdvisors;
        }

     2.1》 List<Advisor> candidateAdvisors = findCandidateAdvisors(); 获取到所有的Advisor

    org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors如下:

        protected List<Advisor> findCandidateAdvisors() {
            // Add all the Spring advisors found according to superclass rules.
            List<Advisor> advisors = super.findCandidateAdvisors();
            // Build Advisors for all AspectJ aspects in the bean factory.
            if (this.aspectJAdvisorsBuilder != null) {
                advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
            }
            return advisors;
        }

    2.1.1》this.aspectJAdvisorsBuilder.buildAspectJAdvisors()会调用到org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors

        public List<Advisor> buildAspectJAdvisors() {
            List<String> aspectNames = this.aspectBeanNames;
    
            if (aspectNames == null) {
                synchronized (this) {
                    aspectNames = this.aspectBeanNames;
                    if (aspectNames == null) {
                        List<Advisor> advisors = new ArrayList<>();
                        aspectNames = new ArrayList<>();
                        String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                                this.beanFactory, Object.class, true, false);
                        for (String beanName : beanNames) {
                            if (!isEligibleBean(beanName)) {
                                continue;
                            }
                            // We must be careful not to instantiate beans eagerly as in this case they
                            // would be cached by the Spring container but would not have been weaved.
                            Class<?> beanType = this.beanFactory.getType(beanName);
                            if (beanType == null) {
                                continue;
                            }
                            if (this.advisorFactory.isAspect(beanType)) {
                                aspectNames.add(beanName);
                                AspectMetadata amd = new AspectMetadata(beanType, beanName);
                                if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                                    MetadataAwareAspectInstanceFactory factory =
                                            new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                                    List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                                    if (this.beanFactory.isSingleton(beanName)) {
                                        this.advisorsCache.put(beanName, classAdvisors);
                                    }
                                    else {
                                        this.aspectFactoryCache.put(beanName, factory);
                                    }
                                    advisors.addAll(classAdvisors);
                                }
                                else {
                                    // Per target or per this.
                                    if (this.beanFactory.isSingleton(beanName)) {
                                        throw new IllegalArgumentException("Bean with name '" + beanName +
                                                "' is a singleton, but aspect instantiation model is not singleton");
                                    }
                                    MetadataAwareAspectInstanceFactory factory =
                                            new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                                    this.aspectFactoryCache.put(beanName, factory);
                                    advisors.addAll(this.advisorFactory.getAdvisors(factory));
                                }
                            }
                        }
                        this.aspectBeanNames = aspectNames;
                        return advisors;
                    }
                }
            }
    
            if (aspectNames.isEmpty()) {
                return Collections.emptyList();
            }
            List<Advisor> advisors = new ArrayList<>();
            for (String aspectName : aspectNames) {
                List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
                if (cachedAdvisors != null) {
                    advisors.addAll(cachedAdvisors);
                }
                else {
                    MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
                    advisors.addAll(this.advisorFactory.getAdvisors(factory));
                }
            }
            return advisors;
        }

    2.1.2》上面BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false); 获取到Spring IoC中所有的bean的name。

    2.1.3》this.advisorFactory.isAspect(beanType) 判断是否是Aspect切面类,org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory#isAspect如下:

        public boolean isAspect(Class<?> clazz) {
            return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
        }
    
        private boolean hasAspectAnnotation(Class<?> clazz) {
            return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
        }
    
        private boolean compiledByAjc(Class<?> clazz) {
            // The AJTypeSystem goes to great lengths to provide a uniform appearance between code-style and
            // annotation-style aspects. Therefore there is no 'clean' way to tell them apart. Here we rely on
            // an implementation detail of the AspectJ compiler.
            for (Field field : clazz.getDeclaredFields()) {
                if (field.getName().startsWith(AJC_MAGIC)) {
                    return true;
                }
            }
            return false;
        }

    2.1.4》如果是Aspect切面会进行if里面的操作:aspectNames 添加该aspect的名称、并且解析方法内部的advisor通知信息(List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);)

        public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
            Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
            String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
            validate(aspectClass);
    
            // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
            // so that it will only instantiate once.
            MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
                    new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
    
            List<Advisor> advisors = new ArrayList<>();
            for (Method method : getAdvisorMethods(aspectClass)) {
                // Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect
                // to getAdvisor(...) to represent the "current position" in the declared methods list.
                // However, since Java 7 the "current position" is not valid since the JDK no longer
                // returns declared methods in the order in which they are declared in the source code.
                // Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods
                // discovered via reflection in order to support reliable advice ordering across JVM launches.
                // Specifically, a value of 0 aligns with the default value used in
                // AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).
                Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
                if (advisor != null) {
                    advisors.add(advisor);
                }
            }
    
            // If it's a per target aspect, emit the dummy instantiating aspect.
            if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
                Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
                advisors.add(0, instantiationAdvisor);
            }
    
            // Find introduction fields.
            for (Field field : aspectClass.getDeclaredFields()) {
                Advisor advisor = getDeclareParentsAdvisor(field);
                if (advisor != null) {
                    advisors.add(advisor);
                }
            }
    
            return advisors;
        }
    
        private List<Method> getAdvisorMethods(Class<?> aspectClass) {
            final List<Method> methods = new ArrayList<>();
            ReflectionUtils.doWithMethods(aspectClass, method -> {
                // Exclude pointcuts
                if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
                    methods.add(method);
                }
            }, ReflectionUtils.USER_DECLARED_METHODS);
            if (methods.size() > 1) {
                methods.sort(METHOD_COMPARATOR);
            }
            return methods;
        }

      上面代码getAdvisorMethods(aspectClass) 可以看到会解析到@Aspect类里面的方法并且排除掉Pointcut修饰的方法。getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName) 会创建一个Advisor,如下:

        public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
                int declarationOrderInAspect, String aspectName) {
    
            validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
    
            AspectJExpressionPointcut expressionPointcut = getPointcut(
                    candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
            if (expressionPointcut == null) {
                return null;
            }
    
            return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                    this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
        }

    2.2 findAdvisorsThatCanApply 里面根据pointcut里面的方法判断bean可以使用的Advisor

    org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply

        protected List<Advisor> findAdvisorsThatCanApply(
                List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
    
            ProxyCreationContext.setCurrentProxiedBeanName(beanName);
            try {
                return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
            }
            finally {
                ProxyCreationContext.setCurrentProxiedBeanName(null);
            }
        }

    org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply 如下:

        public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
            if (candidateAdvisors.isEmpty()) {
                return candidateAdvisors;
            }
            List<Advisor> eligibleAdvisors = new ArrayList<>();
            for (Advisor candidate : candidateAdvisors) {
                if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
                    eligibleAdvisors.add(candidate);
                }
            }
            boolean hasIntroductions = !eligibleAdvisors.isEmpty();
            for (Advisor candidate : candidateAdvisors) {
                if (candidate instanceof IntroductionAdvisor) {
                    // already processed
                    continue;
                }
                if (canApply(candidate, clazz, hasIntroductions)) {
                    eligibleAdvisors.add(candidate);
                }
            }
            return eligibleAdvisors;
        }
    
        public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
            if (advisor instanceof IntroductionAdvisor) {
                return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
            }
            else if (advisor instanceof PointcutAdvisor) {
                PointcutAdvisor pca = (PointcutAdvisor) advisor;
                return canApply(pca.getPointcut(), targetClass, hasIntroductions);
            }
            else {
                // It doesn't have a pointcut so we assume it applies.
                return true;
            }
        }

    2.3》然后在extendAdvisors(eligibleAdvisors);  将ExposeInvocationInterceptor 加到第一个调用链

    org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#extendAdvisors

        protected void extendAdvisors(List<Advisor> candidateAdvisors) {
            AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
        }

    接着调用: org.springframework.aop.aspectj.AspectJProxyUtils#makeAdvisorChainAspectJCapableIfNecessary

        public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
            // Don't add advisors to an empty list; may indicate that proxying is just not required
            if (!advisors.isEmpty()) {
                boolean foundAspectJAdvice = false;
                for (Advisor advisor : advisors) {
                    // Be careful not to get the Advice without a guard, as this might eagerly
                    // instantiate a non-singleton AspectJ aspect...
                    if (isAspectJAdvice(advisor)) {
                        foundAspectJAdvice = true;
                        break;
                    }
                }
                if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
                    advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
                    return true;
                }
            }
            return false;
        }

     (2) 继续查看org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary 里面获取到Advisor之后调用createProxy 方法创建代理对象

    org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy

        protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
                @Nullable Object[] specificInterceptors, TargetSource targetSource) {
    
            if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
                AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
            }
    
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.copyFrom(this);
    
            if (!proxyFactory.isProxyTargetClass()) {
                if (shouldProxyTargetClass(beanClass, beanName)) {
                    proxyFactory.setProxyTargetClass(true);
                }
                else {
                    evaluateProxyInterfaces(beanClass, proxyFactory);
                }
            }
    
            Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
            proxyFactory.addAdvisors(advisors);
            proxyFactory.setTargetSource(targetSource);
            customizeProxyFactory(proxyFactory);
    
            proxyFactory.setFrozen(this.freezeProxy);
            if (advisorsPreFiltered()) {
                proxyFactory.setPreFiltered(true);
            }
    
            return proxyFactory.getProxy(getProxyClassLoader());
        }

    0》前期准备advisor等操作

    1》org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)  获取代理对象如下:

        public Object getProxy(@Nullable ClassLoader classLoader) {
            return createAopProxy().getProxy(classLoader);
        }

     org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy 获取AOP代理方式如下:

        public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
            if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
                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.");
                }
                if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                    return new JdkDynamicAopProxy(config);
                }
                return new ObjenesisCglibAopProxy(config);
            }
            else {
                return new JdkDynamicAopProxy(config);
            }
        }

     可以看到选择代理工厂的方式是根据ProxyTargetClass来判断。也就是当target有实现接口默认使用JDK代理,否则使用Cglib。当然可以在App上指定强制使用Cglib

    @EnableAspectJAutoProxy(proxyTargetClass  = true)

    2》接下来调用 代理工程生成代理对象:

    2.1》org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)   Jdk代理方式:

        public Object getProxy(@Nullable ClassLoader classLoader) {
            if (logger.isTraceEnabled()) {
                logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
            }
            Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
            findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
            return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
        }

    可以看到使用了JDK的代理模式, InvocationHandler 是自身,也就是处理逻辑在自己内部实现:org.springframework.aop.framework.JdkDynamicAopProxy#invoke

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object oldProxy = null;
            boolean setProxyContext = false;
    
            TargetSource targetSource = this.advised.targetSource;
            Object target = null;
    
            try {
                if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                    // The target does not implement the equals(Object) method itself.
                    return equals(args[0]);
                }
                else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                    // The target does not implement the hashCode() method itself.
                    return hashCode();
                }
                else if (method.getDeclaringClass() == DecoratingProxy.class) {
                    // There is only getDecoratedClass() declared -> dispatch to proxy config.
                    return AopProxyUtils.ultimateTargetClass(this.advised);
                }
                else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                        method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                    // Service invocations on ProxyConfig with the proxy config...
                    return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
                }
    
                Object retVal;
    
                if (this.advised.exposeProxy) {
                    // Make invocation available if necessary.
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }
    
                // Get as late as possible to minimize the time we "own" the target,
                // in case it comes from a pool.
                target = targetSource.getTarget();
                Class<?> targetClass = (target != null ? target.getClass() : null);
    
                // Get the interception chain for this method.
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    
                // Check whether we have any advice. If we don't, we can fallback on direct
                // reflective invocation of the target, and avoid creating a MethodInvocation.
                if (chain.isEmpty()) {
                    // We can skip creating a MethodInvocation: just invoke the target directly
                    // Note that the final invoker must be an InvokerInterceptor so we know it does
                    // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
                    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                    retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
                }
                else {
                    // We need to create a method invocation...
                    MethodInvocation invocation =
                            new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                    // Proceed to the joinpoint through the interceptor chain.
                    retVal = invocation.proceed();
                }
    
                // Massage return value if necessary.
                Class<?> returnType = method.getReturnType();
                if (retVal != null && retVal == target &&
                        returnType != Object.class && returnType.isInstance(proxy) &&
                        !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                    // Special case: it returned "this" and the return type of the method
                    // is type-compatible. Note that we can't help if the target sets
                    // a reference to itself in another returned object.
                    retVal = proxy;
                }
                else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
                    throw new AopInvocationException(
                            "Null return value from advice does not match primitive return type for: " + method);
                }
                return retVal;
            }
            finally {
                if (target != null && !targetSource.isStatic()) {
                    // Must have come from TargetSource.
                    targetSource.releaseTarget(target);
                }
                if (setProxyContext) {
                    // Restore old proxy.
                    AopContext.setCurrentProxy(oldProxy);
                }
            }
        }

    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);    获取到核心的调用链,也就是advice链条。

    可以看到核心的代理逻辑被转交给ReflectiveMethodInvocation,并且传入上面的advice链条。

    org.springframework.aop.framework.ReflectiveMethodInvocation#proceed如下:

        public Object proceed() throws Throwable {
            // We start with an index of -1 and increment early.
            if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
                return invokeJoinpoint();
            }
    
            Object interceptorOrInterceptionAdvice =
                    this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
            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)) {
                    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.
                return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
            }
        }

      关于使用Advice调用链然后调用过程之后研究。

    2.2 》 Cglib创建对象过程:org.springframework.aop.framework.CglibAopProxy#getProxy() 

        @Override
        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;
                if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
                    proxySuperClass = rootClass.getSuperclass();
                    Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                    for (Class<?> additionalInterface : additionalInterfaces) {
                        this.advised.addInterface(additionalInterface);
                    }
                }
    
                // Validate the class, writing log messages as necessary.
                validateClassIfNecessary(proxySuperClass, classLoader);
    
                // Configure CGLIB Enhancer...
                Enhancer enhancer = createEnhancer();
                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);
                enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
    
                Callback[] callbacks = getCallbacks(rootClass);
                Class<?>[] types = new Class<?>[callbacks.length];
                for (int x = 0; x < types.length; x++) {
                    types[x] = callbacks[x].getClass();
                }
                // fixedInterceptorMap only populated at this point, after getCallbacks call above
                enhancer.setCallbackFilter(new ProxyCallbackFilter(
                        this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
                enhancer.setCallbackTypes(types);
    
                // Generate the proxy class and create a proxy instance.
                return createProxyClassAndInstance(enhancer, callbacks);
            }
            catch (CodeGenerationException | IllegalArgumentException ex) {
                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",
                        ex);
            }
            catch (Throwable ex) {
                // TargetSource.getTarget() failed
                throw new AopConfigException("Unexpected AOP exception", ex);
            }
        }

    2.2.1》org.springframework.aop.framework.CglibAopProxy#getCallbacks 获取回调Callback数组如下:(这个就和之前测试的Callback数组一样)

        private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
            // Parameters used for optimization choices...
            boolean exposeProxy = this.advised.isExposeProxy();
            boolean isFrozen = this.advised.isFrozen();
            boolean isStatic = this.advised.getTargetSource().isStatic();
    
            // Choose an "aop" interceptor (used for AOP calls).
            Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
    
            // Choose a "straight to target" interceptor. (used for calls that are
            // unadvised but can return this). May be required to expose the proxy.
            Callback targetInterceptor;
            if (exposeProxy) {
                targetInterceptor = (isStatic ?
                        new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
                        new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
            }
            else {
                targetInterceptor = (isStatic ?
                        new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
                        new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
            }
    
            // Choose a "direct to target" dispatcher (used for
            // unadvised calls to static targets that cannot return this).
            Callback targetDispatcher = (isStatic ?
                    new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
    
            Callback[] mainCallbacks = new Callback[] {
                    aopInterceptor,  // for normal advice
                    targetInterceptor,  // invoke target without considering advice, if optimized
                    new SerializableNoOp(),  // no override for methods mapped to this
                    targetDispatcher, this.advisedDispatcher,
                    new EqualsInterceptor(this.advised),
                    new HashCodeInterceptor(this.advised)
            };
    
            Callback[] callbacks;
    
            // If the target is a static one and the advice chain is frozen,
            // then we can make some optimizations by sending the AOP calls
            // direct to the target using the fixed chain for that method.
            if (isStatic && isFrozen) {
                Method[] methods = rootClass.getMethods();
                Callback[] fixedCallbacks = new Callback[methods.length];
                this.fixedInterceptorMap = new HashMap<>(methods.length);
    
                // TODO: small memory optimization here (can skip creation for methods with no advice)
                for (int x = 0; x < methods.length; x++) {
                    Method method = methods[x];
                    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
                    fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
                            chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
                    this.fixedInterceptorMap.put(method, x);
                }
    
                // Now copy both the callbacks from mainCallbacks
                // and fixedCallbacks into the callbacks array.
                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;
        }

    debug查看获取到的Callbacks链条如下: (DnamicAdvisedInteceptor 也是Cglib代理调用的入口)

     2.2.2》由于是多个Callback,所以需要设置CallbackFilter,否则cglib会报错(不知道应该用哪个Callback-这里没有用链条模式进行依次调用,只是根据CallbackFilter中返回的下标拿到Callback进行单个调用)

    org.springframework.aop.framework.CglibAopProxy.ProxyCallbackFilter#accept 选择方法如下:

            public int accept(Method method) {
                if (AopUtils.isFinalizeMethod(method)) {
                    logger.trace("Found finalize() method - using NO_OVERRIDE");
                    return NO_OVERRIDE;
                }
                if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
                        method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Method is declared on Advised interface: " + method);
                    }
                    return DISPATCH_ADVISED;
                }
                // We must always proxy equals, to direct calls to this.
                if (AopUtils.isEqualsMethod(method)) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Found 'equals' method: " + method);
                    }
                    return INVOKE_EQUALS;
                }
                // We must always calculate hashCode based on the proxy.
                if (AopUtils.isHashCodeMethod(method)) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Found 'hashCode' method: " + method);
                    }
                    return INVOKE_HASHCODE;
                }
                Class<?> targetClass = this.advised.getTargetClass();
                // Proxy is not yet available, but that shouldn't matter.
                List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                boolean haveAdvice = !chain.isEmpty();
                boolean exposeProxy = this.advised.isExposeProxy();
                boolean isStatic = this.advised.getTargetSource().isStatic();
                boolean isFrozen = this.advised.isFrozen();
                if (haveAdvice || !isFrozen) {
                    // If exposing the proxy, then AOP_PROXY must be used.
                    if (exposeProxy) {
                        if (logger.isTraceEnabled()) {
                            logger.trace("Must expose proxy on advised method: " + method);
                        }
                        return AOP_PROXY;
                    }
                    // Check to see if we have fixed interceptor to serve this method.
                    // Else use the AOP_PROXY.
                    if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(method)) {
                        if (logger.isTraceEnabled()) {
                            logger.trace("Method has advice and optimizations are enabled: " + method);
                        }
                        // We know that we are optimizing so we can use the FixedStaticChainInterceptors.
                        int index = this.fixedInterceptorMap.get(method);
                        return (index + this.fixedInterceptorOffset);
                    }
                    else {
                        if (logger.isTraceEnabled()) {
                            logger.trace("Unable to apply any optimizations to advised method: " + method);
                        }
                        return AOP_PROXY;
                    }
                }
                else {
                    // See if the return type of the method is outside the class hierarchy of the target type.
                    // If so we know it never needs to have return type massage and can use a dispatcher.
                    // If the proxy is being exposed, then must use the interceptor the correct one is already
                    // configured. If the target is not static, then we cannot use a dispatcher because the
                    // target needs to be explicitly released after the invocation.
                    if (exposeProxy || !isStatic) {
                        return INVOKE_TARGET;
                    }
                    Class<?> returnType = method.getReturnType();
                    if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
                        if (logger.isTraceEnabled()) {
                            logger.trace("Method return type is assignable from target type and " +
                                    "may therefore return 'this' - using INVOKE_TARGET: " + method);
                        }
                        return INVOKE_TARGET;
                    }
                    else {
                        if (logger.isTraceEnabled()) {
                            logger.trace("Method return type ensures 'this' cannot be returned - " +
                                    "using DISPATCH_TARGET: " + method);
                        }
                        return DISPATCH_TARGET;
                    }
                }
            }

    2.2.3》org.springframework.aop.framework.CglibAopProxy#createProxyClassAndInstance 如下:

        protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
            enhancer.setInterceptDuringConstruction(false);
            enhancer.setCallbacks(callbacks);
            return (this.constructorArgs != null && this.constructorArgTypes != null ?
                    enhancer.create(this.constructorArgTypes, this.constructorArgs) :
                    enhancer.create());
        

          至此,cglib 代理对象创建完成。

       对象创建完成之后会返回代理对象,然后放入容器中,也就是容器存放的是代理对象作为对应beanName的primary对象。

       下节研究AOP的调用过程。 

    【当你用心写完每一篇博客之后,你会发现它比你用代码实现功能更有成就感!】
  • 相关阅读:
    杭电ACM1.1.4
    杭电ACM1.2.1 Elevator
    杭电ACM1.2.3 QuickSum
    杭电ACM1.2.5 Balloon Comes!
    ProxySQL 读写分离实践
    MySQL 5.7 新特性之初始化
    MySQL高可用架构之MHA 原理与实践
    CentOS 7 快速初始化脚本 for MySQL
    基于Mysql 5.7 GTID 搭建双主Keepalived 高可用
    MySQL 5.7 新特性之增强半同步复制
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/14457501.html
Copyright © 2011-2022 走看看