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的调用过程。 

补充: 关于SpringAOP 顺序问题 

1. 比如如下三个AOP:

MyAdvice:

package com.zd.bx.beantest.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect // 表示该类是一个通知类
@Component // 交给spring管理
public class MyAdvice {
    // 定义一个空方法,借用其注解抽取切点表达式
    @Pointcut("execution(* com.zd.bx.beantest.service..*.*(..))")
    public void pc() {
    }

    // 环绕通知(推荐下面这种方式获取方法)
    @Around("MyAdvice.pc()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("----------------环绕通知之前 的部分----------------");
        Object proceed = pjp.proceed();
        //环绕通知之后的业务逻辑部分
        System.out.println("----------------环绕通知之后的部分----------------");
        return proceed;
    }

}
View Code

MyAdvice2:

package com.zd.bx.beantest.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect // 表示该类是一个通知类
@Component // 交给spring管理
public class MyAdvice2 {
    // 定义一个空方法,借用其注解抽取切点表达式
    @Pointcut("execution(* com.zd.bx.beantest.service..*.*(..))")
    public void pc() {
    }

    // 环绕通知(推荐下面这种方式获取方法)
    @Around("MyAdvice2.pc()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("----------------环绕通知之前 的部分2----------------");
        Object proceed = pjp.proceed();

        System.out.println("----------------环绕通知之后的部分2----------------");
        return proceed;
    }
}
View Code

MyAdvicer:

package com.zd.bx.beantest.aop;

import org.aopalliance.aop.Advice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.stereotype.Component;

@Component
public class MyAdvicer implements PointcutAdvisor {

    @Override
    public Advice getAdvice() {
        return new MyInterceptor();
    }

    @Override
    public boolean isPerInstance() {
        return true;
    }

    @Override
    public Pointcut getPointcut() {
        return new MyPoint();
    }
}



========
package com.zd.bx.beantest.aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println(invocation.getMethod() + "==MyInterceptor 方法执行前==");
        Object proceed = invocation.proceed();
        System.out.println(invocation.getArguments() + "--MyInterceptor 方法执行后--");
        return proceed;
    }

}



========
package com.zd.bx.beantest.aop;

import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;

import java.lang.reflect.Method;

public class MyPoint implements Pointcut {

    @Override
    public ClassFilter getClassFilter() {
        return new ClassFilter() {
            @Override
            public boolean matches(Class<?> clazz) {
                if (clazz != null && clazz.getName().contains("com.zd.bx.beantest.service")) {
                    return true;
                }

                return false;
            }
        };
    }

    @Override
    public MethodMatcher getMethodMatcher() {

        return new MethodMatcher() {
            /**
             * 判断方法是否匹配
             */
            @Override
            public boolean matches(Method method, Class<?> targetClass, Object... args) {
                return "test1".equals(method.getName());
            }

            /**
             * 判断方法是否匹配
             */
            @Override
            public boolean matches(Method method, Class<?> targetClass) {
                return "test1".equals(method.getName());
            }

            @Override
            public boolean isRuntime() {
                return false;
            }
        };
    }
}
View Code

2. 执行一个方法查看其执行如下, 对于如下bean:

package com.zd.bx.beantest.service;

import org.springframework.beans.factory.BeanNameAware;

public class Bean1 implements BeanNameAware {

    public void test1() {
        System.out.println("1112222");
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("Bean1 beanName: " + s);
    }
}

执行结果:

public void com.zd.bx.beantest.service.Bean1.test1()==MyInterceptor 方法执行前==
----------------环绕通知之前 的部分----------------
----------------环绕通知之前 的部分2----------------
1112222
----------------环绕通知之后的部分2----------------
----------------环绕通知之后的部分----------------
[Ljava.lang.Object;@5cae01a5--MyInterceptor 方法执行后--

3. 可以用@Order 指定AOP 执行的顺序。按升序顺序执行, 值越小越靠前

@Component
@Order(800)
public class MyAdvicer implements PointcutAdvisor {

@Aspect // 表示该类是一个通知类
@Component // 交给spring管理
@Order(900)
public class MyAdvice2 {
    
@Aspect // 表示该类是一个通知类
@Component // 交给spring管理
@Order(1000)
public class MyAdvice {
View Code

4. 结果:

public void com.zd.bx.beantest.service.Bean1.test1()==MyInterceptor 方法执行前==
----------------环绕通知之前 的部分2----------------
----------------环绕通知之前 的部分----------------
1112222
----------------环绕通知之后的部分----------------
----------------环绕通知之后的部分2----------------
[Ljava.lang.Object;@706c851b--MyInterceptor 方法执行后--

5 原理查看: 查看其排序过程:

(1) 在对象的生命周期中调用到后期处理器过程, 然后进入判断是否需要进行代理并且创建代理对象过程

(2) org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors 获取可以使用的advisor

    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;
    }

1》 findCandidateAdvisors(); 获取容器中所有的Advisor, 比如上面获取到的为:

result = {ArrayList@6425}  size = 4
 0 = {MyAdvicer@6356} 
 1 = {BeanFactoryTransactionAttributeSourceAdvisor@6432} "org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor: advice org.springframework.transaction.interceptor.TransactionInterceptor@6cd3ad8a"
 2 = {InstantiationModelAwarePointcutAdvisorImpl@6363} "InstantiationModelAwarePointcutAdvisor: expression [MyAdvice.pc()]; advice method [public java.lang.Object com.zd.bx.beantest.aop.MyAdvice.around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; perClauseKind=SINGLETON"
 3 = {InstantiationModelAwarePointcutAdvisorImpl@6371} "InstantiationModelAwarePointcutAdvisor: expression [MyAdvice2.pc()]; advice method [public java.lang.Object com.zd.bx.beantest.aop.MyAdvice2.around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; perClauseKind=SINGLETON"

2》 然后调用 findAdvisorsThatCanApply 保留该bean 可以apply 的Advisor (这里面就是根据Pointcut 判断类是否满足, 类满足再反射获取方法,判断是否有满足的方法,如果有则保留), 因为我没打事务相关注解所以保留后如下:

result = {ArrayList@6437}  size = 3
 0 = {MyAdvicer@6356} 
 1 = {InstantiationModelAwarePointcutAdvisorImpl@6363} "InstantiationModelAwarePointcutAdvisor: expression [MyAdvice.pc()]; advice method [public java.lang.Object com.zd.bx.beantest.aop.MyAdvice.around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; perClauseKind=SINGLETON"
 2 = {InstantiationModelAwarePointcutAdvisorImpl@6371} "InstantiationModelAwarePointcutAdvisor: expression [MyAdvice2.pc()]; advice method [public java.lang.Object com.zd.bx.beantest.aop.MyAdvice2.around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; perClauseKind=SINGLETON"

3》 org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#extendAdvisors 扩展Advisor

    @Override
    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;
    }

  如果有aspectJ类型的Advisor, 则添加一个org.springframework.aop.interceptor.ExposeInvocationInterceptor#INSTANCE 进去,作为advisor 数组的入口Advisor(如果没有Aspect 类型的切面,则不会添加这个默认的Advisor)

方法走完后保留的如下:

result = {ArrayList@6437}  size = 4
 0 = {ExposeInvocationInterceptor$1@6348} "org.springframework.aop.interceptor.ExposeInvocationInterceptor.ADVISOR"
 1 = {MyAdvicer@6356} 
 2 = {InstantiationModelAwarePointcutAdvisorImpl@6363} "InstantiationModelAwarePointcutAdvisor: expression [MyAdvice.pc()]; advice method [public java.lang.Object com.zd.bx.beantest.aop.MyAdvice.around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; perClauseKind=SINGLETON"
 3 = {InstantiationModelAwarePointcutAdvisorImpl@6371} "InstantiationModelAwarePointcutAdvisor: expression [MyAdvice2.pc()]; advice method [public java.lang.Object com.zd.bx.beantest.aop.MyAdvice2.around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; perClauseKind=SINGLETON"

4》 然后走org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#sortAdvisors 对Advisor 进行排序, DEFAULT_PRECEDENCE_COMPARATOR 内部就是走Order 机制进行排序。

    @Override
    protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
        List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
        for (Advisor advisor : advisors) {
            partiallyComparableAdvisors.add(
                    new PartiallyComparableAdvisorHolder(advisor, DEFAULT_PRECEDENCE_COMPARATOR));
        }
        List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
        if (sorted != null) {
            List<Advisor> result = new ArrayList<>(advisors.size());
            for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
                result.add(pcAdvisor.getAdvisor());
            }
            return result;
        }
        else {
            return super.sortAdvisors(advisors);
        }
    }

排序完结果如下:

result = {ArrayList@6515}  size = 4
 0 = {ExposeInvocationInterceptor$1@6348} "org.springframework.aop.interceptor.ExposeInvocationInterceptor.ADVISOR"
 1 = {MyAdvicer@6356} 
 2 = {InstantiationModelAwarePointcutAdvisorImpl@6371} "InstantiationModelAwarePointcutAdvisor: expression [MyAdvice2.pc()]; advice method [public java.lang.Object com.zd.bx.beantest.aop.MyAdvice2.around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; perClauseKind=SINGLETON"
 3 = {InstantiationModelAwarePointcutAdvisorImpl@6363} "InstantiationModelAwarePointcutAdvisor: expression [MyAdvice.pc()]; advice method [public java.lang.Object com.zd.bx.beantest.aop.MyAdvice.around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; perClauseKind=SINGLETON"

 补充:如果有AspectJ 类型的Advosor 切面, 会为Advisor Chain 增加一个默认的org.springframework.aop.interceptor.ExposeInvocationInterceptor

源码如下:

/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.aop.interceptor;

import java.io.Serializable;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import org.springframework.aop.Advisor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.core.NamedThreadLocal;
import org.springframework.core.PriorityOrdered;

/**
 * Interceptor that exposes the current {@link org.aopalliance.intercept.MethodInvocation}
 * as a thread-local object. We occasionally need to do this; for example, when a pointcut
 * (e.g. an AspectJ expression pointcut) needs to know the full invocation context.
 *
 * <p>Don't use this interceptor unless this is really necessary. Target objects should
 * not normally know about Spring AOP, as this creates a dependency on Spring API.
 * Target objects should be plain POJOs as far as possible.
 *
 * <p>If used, this interceptor will normally be the first in the interceptor chain.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 */
@SuppressWarnings("serial")
public final class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {

    /** Singleton instance of this class. */
    public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();

    /**
     * Singleton advisor for this class. Use in preference to INSTANCE when using
     * Spring AOP, as it prevents the need to create a new Advisor to wrap the instance.
     */
    public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
        @Override
        public String toString() {
            return ExposeInvocationInterceptor.class.getName() +".ADVISOR";
        }
    };

    private static final ThreadLocal<MethodInvocation> invocation =
            new NamedThreadLocal<>("Current AOP method invocation");


    /**
     * Return the AOP Alliance MethodInvocation object associated with the current invocation.
     * @return the invocation object associated with the current invocation
     * @throws IllegalStateException if there is no AOP invocation in progress,
     * or if the ExposeInvocationInterceptor was not added to this interceptor chain
     */
    public static MethodInvocation currentInvocation() throws IllegalStateException {
        MethodInvocation mi = invocation.get();
        if (mi == null) {
            throw new IllegalStateException(
                    "No MethodInvocation found: Check that an AOP invocation is in progress and that the " +
                    "ExposeInvocationInterceptor is upfront in the interceptor chain. Specifically, note that " +
                    "advices with order HIGHEST_PRECEDENCE will execute before ExposeInvocationInterceptor! " +
                    "In addition, ExposeInvocationInterceptor and ExposeInvocationInterceptor.currentInvocation() " +
                    "must be invoked from the same thread.");
        }
        return mi;
    }


    /**
     * Ensures that only the canonical instance can be created.
     */
    private ExposeInvocationInterceptor() {
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        MethodInvocation oldInvocation = invocation.get();
        invocation.set(mi);
        try {
            return mi.proceed();
        }
        finally {
            invocation.set(oldInvocation);
        }
    }

    @Override
    public int getOrder() {
        return PriorityOrdered.HIGHEST_PRECEDENCE + 1;
    }

    /**
     * Required to support serialization. Replaces with canonical instance
     * on deserialization, protecting Singleton pattern.
     * <p>Alternative to overriding the {@code equals} method.
     */
    private Object readResolve() {
        return INSTANCE;
    }

}
View Code

  可以理解其作用主要是为了传递MethodInvocation 对象。

 

posted @ 2021-02-28 11:04  QiaoZhi  阅读(750)  评论(0编辑  收藏  举报