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的流程
定义切面类
- 自定义注解
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 {
}
- 切面类(切入点+增强逻辑)
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注解
package spring.aop;import org.springframework.stereotype.Service;@Service
public class AccountService {/*** 需要被增强的方法*/@Logpublic 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注解的方法
一、测试结果
- 从容器中获取到的是代理对象
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方法)
- 执行目标方法(通过反射调用目标方法)
- 执行后置增强逻辑(同样是通过反射执行切面类的后置增强逻辑)