Spring的AOP底层解析

2022-10-30 16:05:58 浏览数 (1)

AOP原理的前置知识

  (1)动态代理(具体可查看  java的动态代理底层解析 )

      动态代理在Spring中的应用:

        1.AOP

        2.注解@Lazy

  (2)Spring中针对动态代理的封装

      1.ProxyFactory 

        (1)介绍

            基于两种动态代理技术,在Spring中进行了封装,封装出来的类叫做ProxyFactory,表示是创建代理对象的一个工厂,使用起来会更加方便。

        (2)简单使用

            通过ProxyFactory,我们可以不再关系到底是用cglib还是jdk动态代理了,ProxyFactory会帮我们去判断,如果UserService实现了接口,那么ProxyFactory底层就会用jdk动态代理,如果没有实现接口,就会用cglib技术。

代码语言:javascript复制
UserService userService1 = new UserService();

ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(userService1);
proxyFactory.addAdvice(new MethodInterceptor() {
    @Nullable
    @Override
    public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
        System.out.println("切面逻辑 before...");
        Object result = invocation.proceed();  //执行被代理的方法,用于传递句柄
        //invocation.getMethod().invoke(invocation.getThis(), invocation.getArguments()); //执行被代理对象的方法
        System.out.println("切面逻辑 after...");
        return result;
    }
});

UserService userService2  = (UserService) proxyFactory.getProxy();
userService2.test();

        (3)方法说明

           1、setTarget(),创建一个单例的代理对象

           2、addAdvice添加代理方法,该方法实现了Advice接口

             3、getProxy() 获取代理对象,AOP代理的Bean是通过该方法增强的

        (4)Advice的分类 

            据我们想要对方法增强的话会有以下情况:

              1. Before Advice:方法之前执行(对应MethodBeforeAdvice接口)

代码语言:javascript复制
public interface MethodBeforeAdvice extends BeforeAdvice {
    void before(Method method, Object[] args, @Nullable Object target) throws Throwable;
}

              2. After returning advice:方法return后执行 (对应AfterReturningAdvice接口)

代码语言:javascript复制
public interface AfterReturningAdvice extends AfterAdvice {
    void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable;
}

              3. After throwing advice:方法抛异常后执行(对应ThrowsAdvice接口)

代码语言:javascript复制
/**
 * 注解上的示例
 * <pre class="code">void afterThrowing([Method, args, target], ThrowableSubclass);</pre>
 * <p>Some examples of valid methods would be:
 *
 * <pre class="code">public void afterThrowing(Exception ex)</pre>
 * <pre class="code">public void afterThrowing(RemoteException)</pre>
 * <pre class="code">public void afterThrowing(Method method, Object[] args, Object target, Exception ex)</pre>
 * <pre class="code">public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)</pre>
 */
public interface ThrowsAdvice extends AfterAdvice {}

//为什么不定义方法,因为对于异常可以自定义,根据自己定义的不同异常进行捕捉执行拦截方法

              4. After (finally) advice:方法执行完finally之后执行,这是最后的,比return更后(对应AfterAdvice接口)

              5. Around advice:这是功能最强大的Advice,可以自定义执行顺序(对应MethodInterceptor接口)

代码语言:javascript复制
/**
 * 注解上有着对应的示例
 * <pre class=code>
 * class TracingInterceptor implements MethodInterceptor {
 *   Object invoke(MethodInvocation i) throws Throwable {
 *     System.out.println("method " i.getMethod() " is called on " 
 *                        i.getThis() " with args " i.getArguments());
 *     Object ret=i.proceed();
 *     System.out.println("method " i.getMethod() " returns " ret);
 *     return ret;
 *   }
 * }
 * </pre>
 */
public interface MethodInterceptor extends Interceptor {
    Object invoke(MethodInvocation invocation) throws Throwable;
}

        (5)链路形成的原理

            1.addAdvice添加代理方法展示(既然有多个,那么调用的时候必然也要都调用)

代码语言:javascript复制
//这个方法本质上最终是将advisor参数添加到this.advisors属性里面
public void addAdvisor(Advisor advisor) {
    int pos = this.advisors.size();
    addAdvisor(pos, advisor);
}

            2.拦截器的句柄传递(分析invocation.proceed())

代码语言:javascript复制
//ReflectiveMethodInvocation类#proceed()方法
public Object proceed() throws Throwable {

    // currentInterceptorIndex初始值为-1,每调用一个interceptor就会加1,当调用完了最后一个interceptor后就会执行被代理方法
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return invokeJoinpoint();
    }

    // currentInterceptorIndex初始值为-1,根据下标获取拦截器
    Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(  this.currentInterceptorIndex);

    // 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor
    // 如果没有匹配则递归调用proceed()方法,调用下一个interceptor
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {

        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 {
            // 不匹配则执行下一个MethodInterceptor
            return proceed();
        }
    }
    else {
        // 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归,如:MethodBeforeAdviceInterceptor
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

protected Object invokeJoinpoint() throws Throwable {
    return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}

AopUtils类#invokeJoinpointUsingReflection方法
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args) throws Throwable {
    try {
        ReflectionUtils.makeAccessible(method);
        // 执行普通对象的方法,注意和@Configuration产生的代理对象的逻辑区别
        return method.invoke(target, args);
    }
    catch (InvocationTargetException ex) {...} catch (IllegalArgumentException ex) {...} catch (IllegalAccessException ex) {...}
}

        (6)Advisor的理解

          1.介绍说明

            跟Advice类似的还有一个Advisor的概念,一个Advisor是有一个Pointcut和一个Advice组成的,通过Pointcut可以指定要需要被代理的逻辑,比如一个UserService类中有两个方法,按上面的方法,这两个方法都会被代理,被增强,那么我们现在可以通过Advisor,来控制到具体代理哪一个方法。

          2.代码示例(产生的代理对象,只有在执行testAbc这个方法时才会被增强,会执行额外的逻辑,而在执行其他方法时是不会增强的)

代码语言:javascript复制
public class UserServiceImpl implements UserService {
    @Override
    public String doSomething0(String param) {
        System.out.println("==============doSomething0");
        return "doSomething0";
    }

    @Override
    public String doSomething1(String param) {
        System.out.println("==============doSomething1");
        return "doSomething1";
    }

    @Override
    public String doSomething2(String param) {
        System.out.println("==============doSomething2");
        return "doSomething2";
    }

    @Override
    public String myMethod(String param) {
        System.out.println("==============myMethod");
        return "myMethod";
    }
}

//操作代码
UserService userService1 = new UserServiceImpl();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(userService1);
proxyFactory.addAdvisor(new PointcutAdvisor() {
    @Override
    public Pointcut getPointcut() {
        return new StaticMethodMatcherPointcut() {
            @Override
            public boolean matches(Method method, Class<?> targetClass) {
                return method.getName().equals("doSomething1");
            }
        };
    }

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

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

UserService userService2  = (UserService) proxyFactory.getProxy();
userService2.doSomething0("456");

      2.ProxyFactoryBean

        (1)介绍

            在使用Spring时,我们不会直接去使用ProxyFactory,因为我们希望所产生的代理对象能直接就是Bean能直接从Spring容器中得到代理对象,故使用ProxyFactoryBean。

        (2)简单使用

            通过这种方法来定义一个Bean,并且是经过了AOP的。但是这种方式只能针对某一个Bean。它是一个FactoryBean,所以利用的就是FactoryBean技术,间接的将类的代理对象作为了Bean。

            方法1:

代码语言:javascript复制
@Bean
public ProxyFactoryBean userService1() {
    UserService userService = new UserService();
    ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
    proxyFactoryBean.setTarget(userService);
    proxyFactoryBean.addAdvisor(new PointcutAdvisor() {
        @Override
        public Pointcut getPointcut() {
            return new StaticMethodMatcherPointcut() {
                @Override
                public boolean matches(Method method, Class<?> targetClass) {
                    return method.getName().equals("doSomething1");
                }
            };
        }

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

        @Override
        public boolean isPerInstance() {
            return false;
        }
    });
    return proxyFactoryBean;
}
代码语言:txt复制
   方法2:
代码语言:javascript复制
//把某个Advise或Advisor定义成为Bean,然后在ProxyFactoryBean中进行设置
@Bean
public MyAroundAdvice MyAroundAdvise() {
    return new MyAroundAdvice();
}


@Bean
public ProxyFactoryBean userService() {
    UserService userService = new UserService();
    ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
    proxyFactoryBean.setProxyTargetClass(true);
    proxyFactoryBean.setTarget(userService);
    proxyFactoryBean.setInterceptorNames("myAroundAdvise");
    return proxyFactoryBean;
}

      3.BeanNameAutoProxyCreator

        (1)介绍

            根据继承关系可知BeanNameAutoProxyCreator类继承了AbstractAdvisorAutoProxyCreator类(AbstractAutoProxyCreator有个抽象方法getAdvicesAndAdvisorsForBean方法)

            该类实现SmartInstantiationAwareBeanPostProcessor接口(该接口继承InstantiationAwareBeanPostProcessor接口【用于实例化的接口】)

            ProxyFactoryBean得自己指定被代理的对象,那么我们可以通过BeanNameAutoProxyCreator来通过指定某个bean的名字,来对该bean进行代理。

            通过BeanNameAutoProxyCreator可以对批量的Bean进行AOP,并且指定了代理逻辑,指定了一个InterceptorName,也就是一个Advise,前提条件是这个Advise也得是一个Bean,这样Spring才能找到的,但是BeanNameAutoProxyCreator的缺点很明显,它只能根据beanName来指定想要代理的Bean。

        (2)简单使用

代码语言:javascript复制
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
    BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
    beanNameAutoProxyCreator.setBeanNames("userSe*");
    beanNameAutoProxyCreator.setInterceptorNames("myAroundAdvise");
    beanNameAutoProxyCreator.setProxyTargetClass(true);

    return beanNameAutoProxyCreator;
}

      4.DefaultAdvisorAutoProxyCreator

        (1)介绍

            根据继承关系可知DefaultAdvisorAutoProxyCreator类继承了AbstractAdvisorAutoProxyCreator类(AbstractAutoProxyCreator有个抽象方法getAdvicesAndAdvisorsForBean方法)

            该类实现SmartInstantiationAwareBeanPostProcessor接口(该接口继承InstantiationAwareBeanPostProcessor接口【用于实例化的接口】)

        (2)简单使用

代码语言:javascript复制
@Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor() {
    NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
    pointcut.addMethodName("test");

    DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
    defaultPointcutAdvisor.setPointcut(pointcut);
    defaultPointcutAdvisor.setAdvice(new MyAroundAdvice());

    return defaultPointcutAdvisor;
}

@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);

    return defaultAdvisorAutoProxyCreator;
}

        (3)思想说明

            1.通过DefaultAdvisorAutoProxyCreator会去找所有Advisor类型的Bean,根据Advisor中的PointCut和Advice信息,确定要代理的Bean以及代理逻辑。

            2.但通过这种方式,我们得依靠某一个类来实现定义我们的Advisor,或者Advise,或者Pointcut。

            3.要知道在bean的生命周期中存在BeanDefinition获取bean的元数据,为了更简化那就通过注解。

            4.通过在类中的方法上通过某些注解,来定义PointCut以及Advice,如

代码语言:javascript复制
@Pointcut("execution(public * com.xxx.test.service.*.*(..))")
public void pc1(){}


@Around("pc1()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("==============AspectAnnotation around前置通知=========");
    Object result = joinPoint.proceed();
    System.out.println("==============AspectAnnotation around后置通知=========");
    return result;
}

//或者
@Around(""execution(public void com.xxx.test.service.UserService.test())"")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("==============AspectAnnotation around前置通知=========");
    Object result = joinPoint.proceed();
    System.out.println("==============AspectAnnotation around后置通知=========");
    return result;
}

            5.直接定义好了所要代理的方法(通过一个表达式),以及代理逻辑(被@Before修饰的方法),这样对于Spring来说,它要做的就是来解析这些注解了,解析之后得到对应的Pointcut对象、Advice对象,生成Advisor对象,扔进ProxyFactory中,进而产生对应的代理对象。

      5.TargetSource

        (1)介绍

            AOP中,被代理对象就是Bean对象,是由BeanFactory给我们创建出来的,但Spring AOP中提供了TargetSource机制,可以让我们用来自定义逻辑来创建被代理对象。

        (2)简单使用

代码语言:javascript复制
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTargetSource(new TargetSource() {
    @Override
    public Class<?> getTargetClass() {
        return UserService.class;
    }

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

    @Override
    public Object getTarget() throws Exception {
        return new UserService();
    }

    @Override
    public void releaseTarget(Object target) throws Exception {

    }
});

proxyFactory.addAdvice(new MyAroundAdvice());
proxyFactory.setProxyTargetClass(true);
proxyFactory.setFrozen(true); // frozen和static都为true,可以使得代理对象执行方法是保证被代理对象是同一个
UserService proxy = (UserService) proxyFactory.getProxy();
proxy.test();

        (3)简单说明

            1.首先proxyFactory要产生代理对象离不开被代理对象。那么我们要先知道setTarget与setTargetSource之间的关联:

代码语言:javascript复制
public void setTarget(Object target) {
    setTargetSource(new SingletonTargetSource(target));
}

@Override
public void setTargetSource(@Nullable TargetSource targetSource) {
    this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
}

            2.通过源码可以看到即使是设置Target,其实都会被包装成TargetSource,那么对应的要获取Target,也就只能调用TargetSource类#getTarget()方法。(说明proxy代理的不是target,而是TargetSource)

            3.通常情况下,一个代理对象只能代理一个target,每次方法调用的目标也是唯一固定的target。但让proxy代理TargetSource,可以使得每次方法调用的target实例都不同(当然也可以相同,这取决于TargetSource实现)。这种机制使得方法调用变得灵活,可以扩展出很多高级功能,如:单利,原型,本地线程,目标对象池、运行时目标对象热替换目标源等等。(具体可查看   TargetSource目标源详解  )

对AOP的理解

  1. OOP表示面向对象编程,是一种编程思想,AOP表示面向切面编程,也是一种编程思想,而我们上面所描述的就是Spring为了让程序员更加方便的做到面向切面编程所提供的技术支持,也就说Spring提供了一套机制,可以让我们更加容易的来进行AOP,所以这套机制我们也可以称之为Spring AOP。
  2. 但提供的注解的方式来定义Pointcut和Advice,Spring并不是首创,首创是AspectJ,而且也不仅仅只有Spring提供了一套机制来支持AOP,还有比如 JBoss 4.0、aspectwerkz等技术都提供了对于AOP的支持。而且注解的方式,Spring是依赖了AspectJ的,Spring是直接把AspectJ中所定义的那些注解直接拿过来用,自己没有再重复定义了,也仅仅只是把注解的定义赋值过来了,每个注解具体底层是怎么解析的,还是Spring自己做的,所以在用Spring时,如果你想用@Before、@Around等注解,是需要单独引入aspecj相关jar包的。
  3. 注意:AspectJ是在编译时对字节码进行了修改,是直接在UserService类对应的字节码中进行增强的,也就是可以理解为是在编译时就会去解析@Before这些注解,然后得到代理逻辑,加入到被代理的类中的字节码中去的,所以如果想用AspectJ技术来生成代理对象 ,是需要用单独的AspectJ编译器的。我们在项目中很少这么用,仅仅只是用了@Before这些注解,而在启动Spring的过程中,Spring会去解析这些注解,然后利用动态代理机制生成代理对象的。

AOP中的核心概念

  1. Aspect:表示切面,比如被@Aspect注解的类就是切面,可以在切面中去定义Pointcut、Advice等等

  2. Join point:表示连接点,表示一个程序在执行过程中的一个点,比如一个方法的执行,比如一个异常的处理,在Spring AOP中,一个连接点通常表示一个方法的执行。

  3. Advice:表示通知,表示在一个特定连接点上所采取的动作。Advice分为不同的类型,在Spring中是用Interceptor拦截器来实现Advice,并且在连接点周围维护一个Interceptor链。

  4. Pointcut:表示切点,用来匹配一个或多个连接点,Advice与切点表达式是关联在一起的,Advice将会执行在和切点表达式所匹配的连接点上。

  5. Introduction:可以使用@DeclareParents来给所匹配的类添加一个接口,并指定一个默认实现。(这种不怎么用)

      示例

代码语言:javascript复制
public interface CustomInterface {
    public void custom();
}

public class DefaultCustomInterface  implements CustomInterface{

    @Override
    public void custom() {
        System.out.println("custom..");
    }
}

@Aspect
@Component
public class MyAspect {

    //这种方式需要引入AspectJ
    @DeclareParents(value = "com.test.aop.introduction.CustomService", defaultImpl = DefaultCustomInterface.class)
    private CustomInterface customInterface;
}

@ComponentScan
@Configuration
@EnableAspectJAutoProxy
public class IntroductionDemo {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext  = new AnnotationConfigApplicationContext(IntroductionDemo.class);
        CustomService customService = applicationContext.getBean(CustomService.class);
        CustomInterface customInterface = (CustomInterface) customService;
        customInterface.custom();
    }
}

  6. Target object:目标对象,被代理对象

  7. AOP proxy:表示代理工厂,用来创建代理对象的,在Spring Framework中,要么是JDK动态代理,要么是CGLIB代理

  8. Weaving:表示织入,表示创建代理对象的动作,这个动作可以发生在编译时期(比如Aspejctj),或者运行时【如Spring AOP】。

Advice在Spring AOP中对应API

  (1)Aspject中的注解,其中有五个是用来定义Advice的,表示代理逻辑,以及执行时机:

      1. @Before       2. @AfterReturning       3. @AfterThrowing       4. @After       5. @Around   (2)Spring自己也提供了类似的执行实际的实现类:       1. 接口MethodBeforeAdvice,继承了接口BeforeAdvice       2. 接口AfterReturningAdvice       3. 接口ThrowsAdvice       4. 接口AfterAdvice       5. 接口MethodInterceptor   (3)Spring会把五个注解解析为对应的Advice类:       1. @Before:AspectJMethodBeforeAdvice,实际上就是一个MethodBeforeAdvice       2. @AfterReturning:AspectJAfterReturningAdvice,实际上就是一个AfterReturningAdvice       3. @AfterThrowing:AspectJAfterThrowingAdvice,实际上就是一个MethodInterceptor       4. @After:AspectJAfterAdvice,实际上就是一个MethodInterceptor       5. @Around:AspectJAroundAdvice,实际上就是一个MethodInterceptor

ProxyFactory源码解析

  1.怎么判断是使用哪种动态代理?

代码语言:javascript复制
//ProxyFactory类#getProxy()方法
public Object getProxy() {
    //createAopProxy()在底层筛选方式
    //getProxy()方法返回代理对象
    return createAopProxy().getProxy();
}


//ProxyCreatorSupport类#createAopProxy()方法
protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }
    //调用DefaultAopProxyFactory类(实现类AopProxyFactory接口)#createAopProxy(AdvisedSupport config)方法
    return getAopProxyFactory().createAopProxy(this);
}

//DefaultAopProxyFactory类#createAopProxy方法
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

    // 是不是在GraalVM虚拟机上运行
    if (!NativeDetector.inNativeImage() &&
            // 如果ProxyFactory的isOptimize为true,Spring认为cglib比jdk动态代理要快
            // 或者isProxyTargetClass为true
            // 或者ProxyFactory有没有添加接口[setInterfaces()方法]
            (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.");
        }
        //被代理的类是接口【setTargetClass】
        //判断是不是已经被代理的类
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        return new JdkDynamicAopProxy(config);
    }
}

  2.两种类型怎么产生动态代理的?

    (1)CGLib动态代理

代码语言:javascript复制
public Object getProxy() {
    return getProxy(null);
}

//删减日志与抛出异常部分
//CglibAopProxy类#getProxy方法
public Object getProxy(@Nullable ClassLoader classLoader) {
    try {
        // 被代理的类
        Class<?> rootClass = this.advised.getTargetClass();

        Class<?> proxySuperClass = rootClass;
        // 如果被代理类本身就已经是Cglib所生成的代理类了
        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));

        // 获取和被代理类所匹配的Advisor
        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);

        //返回产生的代理对象
        return createProxyClassAndInstance(enhancer, callbacks);
    }
    catch (CodeGenerationException | IllegalArgumentException ex) {..}
    catch (Throwable ex) {..}
}

    (2)JDK动态代理

代码语言:javascript复制
public Object getProxy() {
    return getProxy(ClassUtils.getDefaultClassLoader());
}

//JdkDynamicAopProxy类#getProxy方法
public Object getProxy(@Nullable ClassLoader classLoader) {
    // this实现了InvocationHandler
    return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}

  3.两种类型的执行逻辑是怎么样的?

    (1)JDK动态代理

        1.JdkDynamicAopProxy类#invoke方法

代码语言:javascript复制
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;

    // 拿到ProxyFactory的配置对象【属性值private final AdvisedSupport advised;(AdvisedSupport是实现ProxyConfig配置接口的)】
    TargetSource targetSource = this.advised.targetSource;
    Object target = null;

    try {
        //判断如果被代理的目标对象要执行的方法是equal则执行JdkDynamicAopProxy(即代理对象的equal)方法,说明spring不对equal方法进行AOP拦截
        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            return equals(args[0]);
        }
        //判断如果被代理的目标对象要执行的方法是hashcode则执行JdkDynamicAopProxy(即代理对象的hashcode)方法,同理spring也不对hashcode进行AOP拦截
        else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            return hashCode();
        }
        else if (method.getDeclaringClass() == DecoratingProxy.class) {
            // 得到代理对象的类型,而不是所实现的接口
            return AopProxyUtils.ultimateTargetClass(this.advised);
        }
        //判断如果被代理的对象本身就是实现了Advised接口,也不做处理,直接执行,说明spring不做切面的切面
        else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&  method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
        }

        Object retVal;

        // 如果ProxyFactory的exposeProxy为true(可以对外暴露),则将代理对象设置到currentProxy这个ThreadLocal中去
        if (this.advised.exposeProxy) {
            //将代理对象设置到currentProxy这个ThreadLocal中去,作用是能通过ThreadLocal获取当前的代理对象(能在自己写的方法里面拿到代理对象)
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }

        // 被代理对象和代理类
        target = targetSource.getTarget();
        Class<?> targetClass = (target != null ? target.getClass() : null);

        // 代理对象在执行某个方法时,根据方法筛选出匹配的Advisor,并适配成Interceptor
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

        if (chain.isEmpty()) {
            // 如果没有Advice,则直接调用对应方法
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        }
        else {
            //包装成方法对象反射调用句柄
            MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, 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())) {
            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()) {
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

        2.AdvisedSupport类#getInterceptorsAndDynamicInterceptionAdvice方法

代码语言:javascript复制
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
    // 代理对象在执行某个方法时,会根据当前ProxyFactory中所设置的Advisor根据当前Method再次进行过滤
    MethodCacheKey cacheKey = new MethodCacheKey(method);

    // 注意这个List,表示的就是Advice链
    // 被代理对象的某个方法已经被调用过,调用第一次就会获取一次,后面多次调用时,则需从缓存中直接获取,无需多次获取,这样就会提高性能
    List<Object> cached = this.methodCache.get(cacheKey);
    if (cached == null) {
        cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
        this.methodCache.put(cacheKey, cached);
    }
    return cached;
}

        3.DefaultAdvisorChainFactory类#getInterceptorsAndDynamicInterceptionAdvice方法

代码语言:javascript复制
//DefaultAdvisorChainFactory类#getInterceptorsAndDynamicInterceptionAdvice方法
public List<Object> getInterceptorsAndDynamicInterceptionAdvice( Advised config, Method method, @Nullable Class<?> targetClass) {

    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

    // 从ProxyFactory中拿到所设置的Advice(添加时被封装成了DefaultPointcutAdvisor),添加的时候会控制顺序
    Advisor[] advisors = config.getAdvisors();
    List<Object> interceptorList = new ArrayList<>(advisors.length);
    Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
    Boolean hasIntroductions = null;

    //遍历每个advisor
    for (Advisor advisor : advisors) {
        if (advisor instanceof PointcutAdvisor) {

            PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
            // 先匹配类
            if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {

                // 再匹配方法
                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                boolean match;
                if (mm instanceof IntroductionAwareMethodMatcher) {
                    if (hasIntroductions == null) {
                        hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                    }
                    match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
                }
                else {
                    match = mm.matches(method, actualClass);
                }

                if (match) {
                    // 如果匹配则将Advisor封装成为Interceptor,当前Advisor中的Advice可能即是MethodBeforeAdvice,也是ThrowsAdvice
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    if (mm.isRuntime()) {
                        for (MethodInterceptor interceptor : interceptors) {
                  // 运行时,封装成对应的 InterceptorAndDynamicMethodMatcher 拦截器对象。
                            interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                        }
                    }
                    else {
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }

                // 最终,interceptorList中存储的是当前正在执行的Method所匹配的MethodInterceptor,可能动态的,也可能是非动态的,
                // 找到Method所匹配的MethodInterceptor后,就会开始调用这些MethodInterceptor,如果是动态的,会额外进行方法参数的匹配
            }
        } 
        //下面便是采用了修饰器模式的思维,把所有的拦截类型都转为Interceptor方便后面调用
        else if (advisor instanceof IntroductionAdvisor) {
            IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
            if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }
        else {
            // 将Advisor封装成为Interceptor
            Interceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
        }
    }

    return interceptorList;
}

        4.DefaultAdvisorAdapterRegistry类#getInterceptors方法(拦截器包装)

代码语言:javascript复制
//作用是将advisor封装成MethodInterceptor
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
    List<MethodInterceptor> interceptors = new ArrayList<>(3);
    Advice advice = advisor.getAdvice();
    if (advice instanceof MethodInterceptor) {
        interceptors.add((MethodInterceptor) advice);
    }
    // 将Advice适配成MethodInterceptor
    for (AdvisorAdapter adapter : this.adapters) {
        if (adapter.supportsAdvice(advice)) {
            interceptors.add(adapter.getInterceptor(advisor));
        }
    }
    if (interceptors.isEmpty()) {
        throw new UnknownAdviceTypeException(advisor.getAdvice());
    }
    return interceptors.toArray(new MethodInterceptor[0]);
}


//初始化的时候就进行了适配器填充
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);

public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());  //作用:包装成new MethodBeforeAdviceInterceptor(advice);
	registerAdvisorAdapter(new AfterReturningAdviceAdapter());  //作用:包装成new AfterReturningAdviceInterceptor(advice);
	registerAdvisorAdapter(new ThrowsAdviceAdapter());   //作用:包装成new ThrowsAdviceInterceptor(advisor.getAdvice());
}

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

        5.包装拦截器的部分展示

代码语言:javascript复制
//主要展示invoke逻辑
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
....

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        return mi.proceed();
    }
...
}

public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {
...
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            return mi.proceed();
        }
        catch (Throwable ex) {
            Method handlerMethod = getExceptionHandler(ex);
            if (handlerMethod != null) {
                invokeHandlerMethod(mi, ex, handlerMethod);
            }
            throw ex;
        }
    }
...

}

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
...
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        Object retVal = mi.proceed();
        this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
        return retVal;
    }
...

}


//运行时会进行的封装,因为运行时的方法匹配需要传参
class InterceptorAndDynamicMethodMatcher {

    final MethodInterceptor interceptor;

    final MethodMatcher methodMatcher;

    public InterceptorAndDynamicMethodMatcher(MethodInterceptor interceptor, MethodMatcher methodMatcher) {
        this.interceptor = interceptor;
        this.methodMatcher = methodMatcher;
    }

}

        6.PointcutAdvisor说明(前面如果不太理解的重点要把这个advisor与pointcut与advice关系梳理好)

          (1)使用示例

代码语言:javascript复制
public class MyPointcutAdvisor implements PointcutAdvisor {
    @Override
    public Pointcut getPointcut() {
        return new Pointcut() {
            @Override
            //返回当前切点匹配的类
            public ClassFilter getClassFilter() {
                // return ClassFilter.TRUE;//所有类都匹配
                return new ClassFilter() {
                    @Override
                    //匹配逻辑的写法
                    public boolean matches(Class<?> clazz) {
                        return clazz.equals(UserService.class);
                    }
                };
            }

            @Override
            //返回当前切点匹配的方法
            public MethodMatcher getMethodMatcher() {
                // return MethodMatcher.TRUE;所有方法都匹配
                return new MethodMatcher() {
                    @Override
                    //静态方法匹配器
                    public boolean matches(Method method, Class<?> targetClass) {
                        return false;
                    }

                    @Override
                    //返回false表示是静态方法匹配器,返回true表示是动态方法匹配器
                    public boolean isRuntime() {
                        return false;
                    }

                    @Override
                    //动态方法匹配器
                    public boolean matches(Method method, Class<?> targetClass, Object... args) {
                        return false;
                    }
                };
            }
        };
    }

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

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

    (2)CGLib动态代理

        1.在CGLIB动态代理中,拦截器会被包装成DynamicAdvisedInterceptor类,调用时是调用DynamicAdvisedInterceptor类#intercept方法:

代码语言:javascript复制
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;
    Object target = null;
    TargetSource targetSource = this.advised.getTargetSource();
    try {
        if (this.advised.exposeProxy) {
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }

        target = targetSource.getTarget();
        Class<?> targetClass = (target != null ? target.getClass() : null);
        // 获取当前方法的拦截器链,并执行调用
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
        Object retVal;
        // 检测是否拦截器链是否为空,如果拦截器链为空,那么直接通过反射调用目标对象的方法,避免创建MethodInvocation
        if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
            // 通过反射直接调用目标对象的方法
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = methodProxy.invoke(target, argsToUse);
        }
        else {
            //拦截器链的调用方法proceed与JDK动态代理的proceed是一样的。
            // 创建CglibMethodInvocation对象并调用proceed方法,拦截器链被封装到了retVal中
            retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
        }
        retVal = processReturnType(proxy, target, method, retVal);
        return retVal;
    }
    finally {
        if (target != null && !targetSource.isStatic()) {
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

AOP的引入

  1.核心概念说明

    (1)AbstractAdvisorAutoProxyCreator

代码语言:txt复制
    1. DefaultAdvisorAutoProxyCreator的父类是AbstractAdvisorAutoProxyCreator。
代码语言:txt复制
    2. AbstractAdvisorAutoProxyCreator非常强大以及重要,只要Spring容器中存在这个类型的Bean,就相当于开启了AOP。
    3.  AbstractAdvisorAutoProxyCreator实际上就是一个BeanPostProcessor,所以在创建某个Bean时,就会进入到它对应的生命周期方法中,比如:在某个Bean初始化之后,会调用wrapIfNecessary()方法进行AOP,底层逻辑是,AbstractAdvisorAutoProxyCreator会找到所有的Advisor,然后判断当前这个Bean是否存在某个Advisor与之匹配(根据Pointcut),如果匹配就表示当前这个Bean有对应的切面逻辑,需要进行AOP,需要产生一个代理对象。
 

    (2)注解@EnableAspectJAutoProx

代码语言:txt复制
    1.  这个注解主要就是往Spring容器中添加了一个AnnotationAwareAspectJAutoProxyCreator类型的Bean。
代码语言:txt复制
    2. AspectJAwareAdvisorAutoProxyCreator继承了AbstractAdvisorAutoProxyCreator,重写了findCandidateAdvisors()方法,AbstractAdvisorAutoProxyCreator只能找到所有Advisor类型的Bean对象,但是AspectJAwareAdvisorAutoProxyCreator除开可以找到所有Advisor类型的Bean对象,还能把@Aspect注解所标注的Bean中的@Before等注解及方法进行解析,并生成对应的Advisor对象。
    3.  所以,我们可以理解@EnableAspectJAutoProxy,其实就是像Spring容器中添加了一个AbstractAdvisorAutoProxyCreator类型的Bean,从而开启了AOP,并且还会解析@Before等注解生成Advisor。

  2.注解@EnableAspectJAutoProxy的源码分析 (导入AspectJAutoProxyRegistrar类)

代码语言:javascript复制
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        //注册注解AOP入口类(AnnotationAwareAspectJAutoProxyCreator.class)
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);


        /*
        * * true
         * 1、目标对象实现了接口 – 使用CGLIB代理机制
         * 2、目标对象没有接口(只有实现类) – 使用CGLIB代理机制
         *
         * false
         * 1、目标对象实现了接口 – 使用JDK动态代理机制(代理所有实现了的接口)
         * 2、目标对象没有接口(只有实现类) – 使用CGLIB代理机制
        * */
        AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }

            //是否需要把代理对象暴露出来,简单来说是否需要把代理对象用ThreadLocal存起来,如果是true就是需要
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }
}


//核心点
AnnotationAwareAspectJAutoProxyCreator类的继承关系【】
    extends AbstractAdvisorAutoProxyCreator
        extends AbstractAutoProxyCreator
            AbstractAutoProxyCreator extends ProxyProcessorSupport(这个不重要)
                                     implements SmartInstantiationAwareBeanPostProcessor(这个很重要)
                                         extends InstantiationAwareBeanPostProcessor (该接口用于实例化)
                                             extends BeanPostProcessor(该接口用于初始化前后)

AOP代码的执行逻辑

  1.了解Bean的生命周期,直接跳到初始化后的那一步。AbstractAutowireCapableBeanFactory类#doCreateBean方法里的initializeBean(beanName, exposedObject, mbd)方法。

代码语言:javascript复制
if (mbd == null || !mbd.isSynthetic()) {
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

  2.AnnotationAwareAspectJAutoProxyCreator处理器进行处理

代码语言:javascript复制
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        //拿到AnnotationAwareAspectJAutoProxyCreator处理器进行处理
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

  3.走到AnnotationAwareAspectJAutoProxyCreator类的父类AbstractAutoProxyCreator类的逻辑:

代码语言:javascript复制
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

  4.wrapIfNecessary方法内判断是否进行AOP:

代码语言:javascript复制
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }

    // advisedBeans表示已经判断过了的bean,false表示此bean不需要进行Aop
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }


    // 判断Bean的类是否和切面有关(切面Bean不会被代理)
    // shouldSkip,提供扩展定义哪些类不用进行AOP(其实没怎么用,故不关注)
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // 判断当前bean是否存在匹配的advice,如果存在则要生成一个代理对象
    // 此处根据类以及类中的方法去匹配到Interceptor(也就是Advice),然后生成代理对象,代理对象在执行的时候,还会根据当前执行的方法去匹配
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        // advisedBeans记录了某个Bean已经进行过AOP了
        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);
    //不进行AOP则返回原本的Bean
    return bean;
}

  5.getAdvicesAndAdvisorsForBean方法能否收集到Interceptors是能否进行AOP的重要标记:

代码语言:javascript复制
//AbstractAdvisorAutoProxyCreator类#getAdvicesAndAdvisorsForBean方法
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
    // 寻找匹配的Advisor
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY;
    }
    return advisors.toArray();
}

//AbstractAdvisorAutoProxyCreator类#findEligibleAdvisors方法
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 找到所有的Advisor
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 进行筛选
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);【支线(3)】

    //这是留给子类的扩展(本身没有做什么东西)
    extendAdvisors(eligibleAdvisors);

    // 对Advisor进行排序,按Ordered接口、@Order注解进行排序
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

//AnnotationAwareAspectJAutoProxyCreator类#findCandidateAdvisors方法
protected List<Advisor> findCandidateAdvisors() {
    // 先从Bean工厂中找到所有Advisor类型【也就是实现Advisor接口】的Bean对象【支线(1)】
    List<Advisor> advisors = super.findCandidateAdvisors();

    // 再从所有切面中解析得到Advisor对象【也就是被注解@Aspect修饰的Bean】
    if (this.aspectJAdvisorsBuilder != null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());【支线(2)】
    }
    return advisors;
}

    (1)AbstractAdvisorAutoProxyCreator类#findCandidateAdvisors方法

代码语言:javascript复制
//AbstractAdvisorAutoProxyCreator类#findCandidateAdvisors方法
protected List<Advisor> findCandidateAdvisors() {
    return this.advisorRetrievalHelper.findAdvisorBeans();
}

//BeanFactoryAdvisorRetrievalHelper类#findAdvisorBeans方法
public List<Advisor> findAdvisorBeans() {
    // Determine list of advisor bean names, if not cached already.
    String[] advisorNames = this.cachedAdvisorBeanNames;
    if (advisorNames == null) {
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the auto-proxy creator apply to them!
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                this.beanFactory, Advisor.class, true, false);
        this.cachedAdvisorBeanNames = advisorNames;
    }
    if (advisorNames.length == 0) {
        return new ArrayList<>();
    }

    List<Advisor> advisors = new ArrayList<>();
    for (String name : advisorNames) {
        if (isEligibleBean(name)) {
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Skipping currently created advisor '"   name   "'");
                }
            }
            else {
                try {
                    //从Bean工厂中找出所有实现Advisor接口的Bean
                    advisors.add(this.beanFactory.getBean(name, Advisor.class));
                }
                catch (BeanCreationException ex) {
                    Throwable rootCause = ex.getMostSpecificCause();
                    if (rootCause instanceof BeanCurrentlyInCreationException) {
                        BeanCreationException bce = (BeanCreationException) rootCause;
                        String bceBeanName = bce.getBeanName();
                        if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                            if (logger.isTraceEnabled()) {
                                logger.trace("Skipping advisor '"   name  
                                        "' with dependency on currently created bean: "   ex.getMessage());
                            }
                            // Ignore: indicates a reference back to the bean we're trying to advise.
                            // We want to find advisors other than the currently created bean itself.
                            continue;
                        }
                    }
                    throw ex;
                }
            }
        }
    }
    return advisors;
}

    (2)BeanFactoryAspectJAdvisorsBuilder类#buildAspectJAdvisors方法(封装的Advisor是InstantiationModelAwarePointcutAdvisorImpl类):

代码语言:javascript复制
//BeanFactoryAspectJAdvisorsBuilder类#buildAspectJAdvisors方法
//本方法会被多次调用,因为一个Bean在判断要不要进行AOP时,都会调用这个方法
public List<Advisor> buildAspectJAdvisors() {
    // aspectBeanNames是用来缓存BeanFactory中所存在的切面beanName的,第一次为null,后面就不为null了,不为null表示之前就已经找到过BeanFactory中的切面了
    List<String> aspectNames = this.aspectBeanNames;

    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                List<Advisor> advisors = new ArrayList<>();
                aspectNames = new ArrayList<>();

                // 把所有beanNames拿出来遍历,判断某个bean的类型是否是Aspect
                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, false);
                    if (beanType == null) {
                        continue;
                    }
                    //判断Bean的类型上是不是有@Aspect注解
                    if (this.advisorFactory.isAspect(beanType)) {
                        aspectNames.add(beanName);
                        // 切面的注解信息
                        AspectMetadata amd = new AspectMetadata(beanType, beanName);

                        // 如果@Aspect不是perthis、pertarget,那么一个切面只会生成一个对象(单例)
                        // 并且会将该切面中所对应的Advisor对象进行缓存
                        if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {

                            MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                            // 利用BeanFactoryAspectInstanceFactory来解析Aspect类【将里面的很多切面方法变成Advisor数组】
                            List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                            if (this.beanFactory.isSingleton(beanName)) {
                                // 缓存切面所对应的所有Advisor对象
                                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);
                            // 利用PrototypeAspectInstanceFactory来解析Aspect类
                            // PrototypeAspectInstanceFactory的父类为BeanFactoryAspectInstanceFactory
                            // 这两个Factory的区别在于PrototypeAspectInstanceFactory的构造方法中会判断切面Bean是不是原型,除此之外没有其他区别
                            // 所以主要就是BeanFactoryAspectInstanceFactory来负责生成切面实例对象
                            advisors.addAll(this.advisorFactory.getAdvisors(factory));【调用1】
                        }
                    }
                }
                this.aspectBeanNames = aspectNames;
                return advisors;
            }
        }
    }

    if (aspectNames.isEmpty()) {
        return Collections.emptyList();
    }

    // 如果切面已经找到过了,那么则遍历每个切面是否缓存了对应的Advisor,如果没有缓存则进行解析得到Advisor
    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));【调用1】
        }
    }
    return advisors;
}

//ReflectiveAspectJAdvisorFactory类#getAdvisors方法;【调用1】
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    validate(aspectClass);

    // 保证切面Bean对象只会实例化一次
    // 一定要注意,这里是直接new出来一个LazySingletonAspectInstanceFactoryDecorator
    // 也就是OrderService这个Bean在执行Bean生命周期过程中,会需要判断要不要进行AOP,就会找到切面,
    // 发现切面如果是pertarget或perthis,那么就会进入到这个方法,就会new一个LazySingletonAspectInstanceFactoryDecorator
    // 对于UserService也是一样的,在它的Bean的生命周期过程中,也会进入到这个方法,也会new一个LazySingletonAspectInstanceFactoryDecorator
    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

    List<Advisor> advisors = new ArrayList<>();
    // 获取切面类中没有加@Pointcut的方法,进行遍历生成Advisor
    for (Method method : getAdvisorMethods(aspectClass)) {【调用2】
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);【调用3】
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    // If it's a per target aspect, emit the dummy instantiating aspect.
    // @Aspect("pertarget(this(com.zhouyu.service.UserService))")
    // @Aspect("perthis(this(com.zhouyu.service.UserService))")
    // 如果是pertarget或perthis,则会多生成一个Advisor并放在最前面
    // 在一个代理对象调用方法的时候,就会执行该Advisor,并且会利用lazySingletonAspectInstanceFactory来生成一个切面Bean
    if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
        advisors.add(0, instantiationAdvisor);
    }

    // Find introduction fields.
    // 找到哪些字段上加了@DeclareParents注解,把这些字段以及对于的注解解析封装为Advisor,生成代理对象时会把对于的接口添加到ProxyFactory中
    for (Field field : aspectClass.getDeclaredFields()) {
        Advisor advisor = getDeclareParentsAdvisor(field);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    return advisors;
}

//ReflectiveAspectJAdvisorFactory类#getAdvisorMethods方法【调用2】
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
    List<Method> methods = new ArrayList<>();
    // 拿到切面类中所有没有加@Pointcut的方法
    ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter);
    // 对方法进行排序,按注解和方法名字进行排序
    if (methods.size() > 1) {
        methods.sort(adviceMethodComparator);
    }
    return methods;
}

//ReflectiveAspectJAdvisorFactory类#getAdvisor方法【调用3】
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) {

    validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

    // 拿到当前方法所对应的Pointcut对象,但是注意:如果当前方法上是这么写的@After("pointcut()"),那么此时得到的Pointcut并没有去解析pointcut()得到对应的表达式
    AspectJExpressionPointcut expressionPointcut = getPointcut(
            candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    if (expressionPointcut == null) {
        return null;
    }

    // expressionPointcut是pointcut
    // candidateAdviceMethod承载了advice
    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
            this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

    (3)BeanFactoryAspectJAdvisorsBuilder类#buildAspectJAdvisors方法:

代码语言:javascript复制
//AbstractAdvisorAutoProxyCreator类#findAdvisorsThatCanApply方法
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);【调用1】
    }
    finally {
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}

//AopUtils类#findAdvisorsThatCanApply方法【调用1】
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;
}

  6.createProxy方法进行AOP代理逻辑:

代码语言:javascript复制
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()) {
        // Explicit handling of JDK proxy targets (for introduction advice scenarios)
        if (Proxy.isProxyClass(beanClass)) {
            // Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
            for (Class<?> ifc : beanClass.getInterfaces()) {
                proxyFactory.addInterface(ifc);
            }
        }
    }
    else {
        // No proxyTargetClass flag enforced, let's apply our default checks...
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    // 在这一步会去判断advisors中是否存在IntroductionAdvisor,如果存在则会把对应的interface添加到proxyFactory中去
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    // Use original ClassLoader if bean class not locally loaded in overriding class loader
    ClassLoader classLoader = getProxyClassLoader();
    if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
        classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
    }
    //这里面便是要走我们之前所说的proxyFactory的逻辑
    return proxyFactory.getProxy(classLoader);
}

  7.分析基于注解产生的Advisor的具体实现类InstantiationModelAwarePointcutAdvisorImpl类:

代码语言:javascript复制
//InstantiationModelAwarePointcutAdvisorImpl类#getAdvice方法
public synchronized Advice getAdvice() {
    if (this.instantiatedAdvice == null) {
        this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);【调用1】
    }
    return this.instantiatedAdvice;
}

//调用1
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
    Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
            this.aspectInstanceFactory, this.declarationOrder, this.aspectName);//【调用2】
    return (advice != null ? advice : EMPTY_ADVICE);
}

//【调用2】
//ReflectiveAspectJAdvisorFactory类#getAdvice方法
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

    Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    validate(candidateAspectClass);

    // 拿到当前candidateAdviceMethod方法上的注解信息
    AspectJAnnotation<?> aspectJAnnotation =
            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    if (aspectJAnnotation == null) {
        return null;
    }

    // If we get here, we know we have an AspectJ method.
    // Check that it's an AspectJ-annotated class
    if (!isAspect(candidateAspectClass)) {
        throw new AopConfigException("Advice must be declared inside an aspect type: "  
                "Offending method '"   candidateAdviceMethod   "' in class ["  
                candidateAspectClass.getName()   "]");
    }

    if (logger.isDebugEnabled()) {
        logger.debug("Found AspectJ method: "   candidateAdviceMethod);
    }

    AbstractAspectJAdvice springAdvice;

    // 按不同的注解类型得到不同的Advice
    switch (aspectJAnnotation.getAnnotationType()) {
        case AtPointcut:
            if (logger.isDebugEnabled()) {
                logger.debug("Processing pointcut '"   candidateAdviceMethod.getName()   "'");
            }
            return null;
        case AtAround:
            // @Around
            springAdvice = new AspectJAroundAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtBefore:
            springAdvice = new AspectJMethodBeforeAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtAfter:
            springAdvice = new AspectJAfterAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtAfterReturning:
            springAdvice = new AspectJAfterReturningAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                springAdvice.setReturningName(afterReturningAnnotation.returning());
            }
            break;
        case AtAfterThrowing:
            springAdvice = new AspectJAfterThrowingAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
                springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
            }
            break;
        default:
            throw new UnsupportedOperationException(
                    "Unsupported advice type on method: "   candidateAdviceMethod);
    }

    // Now to configure the advice...
    springAdvice.setAspectName(aspectName);
    springAdvice.setDeclarationOrder(declarationOrder);
    String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
    if (argNames != null) {
        springAdvice.setArgumentNamesFromStringArray(argNames);
    }
    springAdvice.calculateArgumentBindings();

    return springAdvice;
}

AOP底层原理图示

AOP涉及的设计模式

  1.装饰器模式:主要体现在责任链构建中拦截器的包装。

  2.代理模式:主要体现在ProxyFactory生成动态代理。

  3.适配器模式:DefaultAdvisorAdapterRegistry类#getInterceptors方法的选择合适的适配器进行拦截器的包装。

  4.策略模式:主要体现在ProxyFactory选择动态代理类型。

  5.责任链模式:主要体现在构建调用链。

  6.模板设计模式:主要体现在,抽象模板:AbstractAutoProxyCreator类;具体的模板:AnnotationAwareAspectJAutoProxyCreator类。

0 人点赞