Spring之【详解AOP】

目录

前言

定义切面类

registerBeanPostProcessors

一、注册Bean后置处理器,拦截Bean的创建过程

二、使用后置处理器委托执行注册Bean后置处理器的逻辑

三、获取到AnnotationAwareAspectJAutoProxyCreator的beanName

四、创建AnnotationAwareAspectJAutoProxyCreator对象

五、注册AnnotationAwareAspectJAutoProxyCreator

构建Advisors

一、AbstractAutowireCapableBeanFactory的createBean方法中会执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法回调

二、AnnotationAwareAspectJAutoProxyCreator是InstantiationAwareBeanPostProcessor,所以这里会执行到它的postProcessBeforeInstantiation方法(在它的父类AbstractAutoProxyCreator中定义)

三、将增强器放入BeanFactoryAspectJAdvisorsBuilder的advisorsCache集合中

定义一个需要被增强的业务类

创建业务类的代理对象放入单例池中

一、业务类的实例化

二、业务类的初始化

三、Bean后置处理器的初始化后方法回调

四、创建业务类的代理对象

五、放入singletonObjects中的是业务类的代理对象

从容器中获取业务类对象,并执行其添加了@Log注解的方法

一、测试结果

二、通过源码分析其运行流程


前言

  • Spring容器启动时,在AbstractApplicationContext的refresh方法的invokeBeanFactoryPostProcessors这一步骤中执行了ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
  • 该方法会解析到@EnableAspectJAutoProxy注解上的@Import中的value为AspectJAutoProxyRegistrar.class
  • 通过判断得知AspectJAutoProxyRegistrar是ImportBeanDefinitionRegistrar接口的实现类,进而调用到AspectJAutoProxyRegistrar的registerBeanDefinitions方法,将AnnotationAwareAspectJAutoProxyCreator对应的RootBeanDefinition对象放入容器中的beanDefinitionMap集合中
  • AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor,它会在AbstractApplicationContext的refresh方法的registerBeanPostProcessors这一步骤中通过beanFactory的getBean方法进行实例化和初始化得到其对象,并存入AbstractBeanFactory的beanPostProcessors集合中
  • 该BeanPostProcessor将会作用于后续其他bean的getBean的流程

定义切面类

  • 自定义注解
java 复制代码
package spring.aop;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 该注解只能用在方法上
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
}
  • 切面类(切入点+增强逻辑)
java 复制代码
package spring.aop;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 切面
 */
@Aspect
@Component
public class LogAspect {

    /**
     * 切入点表达式
     * 增强有@Log注解的方法
     */
    @Pointcut("@annotation(spring.aop.Log)")
    public void pointCut() {

    }

    /**
     * 定义前置增强逻辑
     */
    @Before("pointCut()")
    public void before() {
        System.out.println("Log...before...");
    }

    /**
     * 定义后置增强逻辑
     */
    @After("pointCut()")
    public void after() {
        System.out.println("Log...after...");
    }
}

registerBeanPostProcessors

一、注册Bean后置处理器,拦截Bean的创建过程

二、使用后置处理器委托执行注册Bean后置处理器的逻辑

三、获取到AnnotationAwareAspectJAutoProxyCreator的beanName

四、创建AnnotationAwareAspectJAutoProxyCreator对象

五、注册AnnotationAwareAspectJAutoProxyCreator

构建Advisors

此时容器中已经有AnnotationAwareAspectJAutoProxyCreator这个后置处理器,它就会作用于接下来Bean的创建过程,在它之后的第一个Bean的getBean过程中,其就会构建Advisors并放入BeanFactoryAspectJAdvisorsBuilder的advisorsCache集合中

一、AbstractAutowireCapableBeanFactory的createBean方法中会执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法回调

二、AnnotationAwareAspectJAutoProxyCreator是InstantiationAwareBeanPostProcessor,所以这里会执行到它的postProcessBeforeInstantiation方法(在它的父类AbstractAutoProxyCreator中定义)

三、将增强器放入BeanFactoryAspectJAdvisorsBuilder的advisorsCache集合中

定义一个需要被增强的业务类

  • 业务类的register方法添加了自定义的@Log注解
java 复制代码
package spring.aop;

import org.springframework.stereotype.Service;

@Service
public class AccountService {
    /**
     * 需要被增强的方法
     */
    @Log
    public void register() {
        System.out.println("AccountService#register...");
    }
}

创建业务类的代理对象放入单例池中

Bean组件在实例化之后会执行初始化逻辑,初始化逻辑中在执行完初始化方法后会执行BeanPostProcessor的postProcessAfterInitialization方法,也就是会执行AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法

一、业务类的实例化

  • getBean
  • doGetBean
  • createBean
  • doCreateBean

二、业务类的初始化

  • Bean属性填充
  • Bean的初始化逻辑

三、Bean后置处理器的初始化后方法回调

  • 执行AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法
  • 为Bean获取增强逻辑

四、创建业务类的代理对象

  • 根据拿到的增强逻辑createProxy
  • 这里是通过CGLIB创建代理对象
  • 拿到了业务类的代理对象,这里可以看到代理对象中既保存了增强逻辑,同时也保存了目标对象

五、放入singletonObjects中的是业务类的代理对象

  • 执行完AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法(实际定义在其父类中)后返回的是Bean的代理对象
  • 将代理对象放入singletonObjects集合中

从容器中获取业务类对象,并执行其添加了@Log注解的方法

一、测试结果

  • 从容器中获取到的是代理对象
java 复制代码
package spring.aop;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AopMain {
    public static void main(String[] args) {
        // 容器启动
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        // 从容器中获取业务类对象
        AccountService accountService = applicationContext.getBean(AccountService.class);
        // 执行其@Log的方法
        accountService.register();
    }
}
  • 执行了增强逻辑

二、通过源码分析其运行流程

  • 开始执行代理对象的方法
  • 执行到CglibAopProxy的intercept方法
  • 获取到目标方法
  • 获取到拦截器链
  • 通过代理对象、目标对象、目标类、目标方法、拦截器链创建ReflectiveMethodInvocation对象
  • 调用proceed方法,currentInterceptorIndex用于记录下标,因为拦截器链是一个List,执行一个可以通过下标++获取下一个
  • 调用MethodInterceptor的invoke方法
  • 拿到前置增强器
  • 执行前置增强逻辑(通过反射调用切面的before方法)
  • 执行目标方法(通过反射调用目标方法)
  • 执行后置增强逻辑(同样是通过反射执行切面类的后置增强逻辑)