AOP 面向切面编程
一. AOP 概述
什么是 AOP : 指定程序在运行期间动态的将某段代码功能切入到指定的位置运行,底层是通过动态代理来实现的
AOP 优点 : 降低代码的耦合,提高代码复用性,提高系统的扩展性
AOP 常见使用场景 : 例如日志记录, 性能统计, 权限控制, 事物处理等
AOP 的实现步骤
- Spring 引入 AOP 需要的依赖
- 设置 Spring 开启 AOP 功能 (xml 方式开启,与注解方式开启)
- 创建存有需要通过 AOP 增强监管的业务代码,并注入到 Spring 容器中
- 创建 AOP 切面类,将切面类注入到 Spring 容器中,
- 告诉 Spring 容器,我是一个切面类 @Aspect
- 切面类中创建通知方法 :
- 前置通知 @Before 目标方法执行前运行
- 后置通知 @After 目标方法执行完毕,或抛出异常时运行
- 返回通知 @AfterReturning 目标方法正常返回之后运行
- 异常通知 @AfterThrowing 目标方法发生异常时运行
- 环绕通知 @Around 该通知中可以获取到被监管的所有数据,可以获取到被监管执行的方法,在环绕通知方法中代理执行,所以可以自定义在被监管的方法前后添加需要执行的其他功能
- 设置通知方法在指定位置标注位置运行,切入点 (需要进行增强的业务代码位置, xml方式, 注解方式 @Pointcut(“execution()”)
Spring 支持 AOP :需要添加依赖
示例
- Spring 中引入 AOP 依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring-version}</version>
</dependency>
- 配置 Spring 开启 AOP 功能
- 注解方式,创建配置类,配置类使用 @EnableAspectJAutoProxy 注解修饰
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.*;
//通过配置类,使用注解的方式开启 Spring 的 aop 功能
@EnableAspectJAutoProxy
@Configuration
public class MyConfiguration {
}
- xml 方式, resources 文件夹中创建.xml配置文件,配置文件中添加 aop:aspectj-autoproxy/ ,注意添加命名空间
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop=http://www.springframework.org/schema/aop
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans"
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd" >
<!--开启aop-->
<aop:aspectj-autoproxy/>
<!--向Spring 容器中注入bean 的包扫描,原因是一般情况下
AOP 切面类与,controller,server,dao,不在一个包下,在使用注解
向spring中注入时,没有扫描,无法注入,如果在一个包下,或其它位置已经扫描过了,则可以不定义-->
<context:component-scan base-package="com.aop.自定义切面类所在的包" />
</beans>
- 创建业务类,编写业务代码,假设在业务代码执行前后,或发生异常时通过 AOP 增加其它功能
@Controller
public class TestController2 {
@RequestMapping(value = "/aoptest", method = RequestMethod.GET)
@ResponseBody
public void aoptest(){
System.out.println("我是被监管的业务代码......");
}
}
- 创建切面类,将切面类注入到 Spring 容器中, 告诉 Spring 我是一个切面类,设置切入点,注入切入点扫描的目标方法所在路径是否正确,定义通知方法
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect //1.代表该类时切面类
@Component //2.将切面类注入到 Spring 容器中
public class LogCut {
//3.定义切入点方法,方法上添加@Pointcut()注解,设置当前切面类监管的目标方法位置
//为了方便可以单独修饰一个空方法,然后通知注解上引用这个方法,也可以直接修饰通知方法
/*解释:execution代表是个表达式
* 扫描 com.ssm.controller 包下的所有类的所有方法
* 第一个星的位置:代表这个方法的权限修饰符,星为任何权限都可以
* com.com.controller 代表哪个包下的
* controller 后的点有两个:一个代表该包下的根目录下的直接类中方法不包括子包
* 两个点代表包括该包下的子包中类的方法
* 点后的第一个星号位置代表包下的类,此处为星号代表任意类
* 第二个星号位置代表方法,此处为星号代表任意方法
* 括号中的两个点,为方法传入的参数类型,此处为两个点代表任意参数*/
@Pointcut("execution(* com.ssm.controller..*.*(..))")
public void cut() {
}
//4.定义通知方法,方法上添加对应的注解,
//前置通知,设置前置通知监管的目标方法
//如果被监管的目标方法有参数需要获取,可以在通知
//方法中定义一个 JoinPoint 的形参,通过这个参数
//可以拿到目标方法的相关数据,注意点 JoinPoint
//这个参数一定要放在形参的第一个位置,否则报错
@Before("cut()")
public void before(JoinPoint joinPoint) {
//获取目标方法签名
Signature signature = joinPoint.getSignature();
//获取目标方法签名获取方法参数
Object [] args = joinPoint.getArgs();
//通过目标方法签名获取目标方法名
String name = signature.getName();
System.out.println("前置通知方法执行,监管了"+name);
}
//返回通知,目标方法如果出现异常没有执行完毕,该通知方法不会执行
//@AfterReturning("cut()")
//如果被监管的方法有返回值,需要获取方法执行后的返回值,可以返回通知注解中
//设置 returning 属性,属性值是返回的数据名,然后在方法形参中定义与该值同名的接收对象
@AfterReturning(value = "cut()", returning = "result")
public void afterReturn(JoinPoint joinPoint, Object result) {
System.out.println("返回通知,正常完毕会执行该方法");
}
//后置通知,不管目标类方法是否发生异常,该通知方法都会执行
@After("cut()")
public void after() {
System.out.println("后置通知,不管是否执行完毕,都会执行");
}
//异常通知目标类方法执行时发生异常执行,
//throwings 代表目标方法抛出的异常,注解中 throwing的值要与方法中形参相同
@AfterThrowing(value = "cut()", throwing = "e")
public void afterThrowing(JoinPoint joinPoint, Exception e) {
System.out.println("异常通知,发生异常时执行该终止" + e);
}
//环绕通知,目标方法执行前后,都可以做出相应的处理
//环绕通知方法中需要传入一个ProceedingJoinPoint对象,该对象可以看为被拦截的方法对象
//在该通知方法中,通过 ProceedingJoinPoint 对象,手动的调用目标方法,
//这样就可以在目标方法前后添加其它操作了
//注意环绕通知与异常通知配合使用时,环绕通知中的逻辑处理如果异常,方法执行后的代码会失效
@Around("cut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知的前置执行");
//通过环绕通知中传入的ProceedingJoinPoint对象可以获取目标类对象中的所有数据
//pjp.getTarget()方法获取到的是目标类对象的内存信息(可以理解为可以获取到目标对象)
//pjp.getSignature()方法可以获取到被代理类的方法
System.out.println(pjp.getTarget() + "----" + pjp.getSignature());
//只需目标方法,被拦截方法执行后执行?(为什么注释了该方法还是会执行后面的)
Object result = pjp.proceed();
System.out.println("环绕通知的后置执行");
return result;
}
}
- 此时如果 TestController2 类中的 aoptest() 方法,被切入点扫描,如果该方法执行,对应的通知方法也会执行
二. 通过 @EnableAspectJAutoProxy 了解 AOP 原理
@EnableAspectJAutoProxy 注解方式,开启 Spring 的 AOP 功能,查看该注解的源码
1. 分析 @EnableAspectJAutoProxy
- 使用 @Import() 修饰,该注解中传递了一个 AspectJAutoProxyRegistrar 类 ,
- 查看 AspectJAutoProxyRegistrar 类,通过该类中的 registerBeanDefinitions() 方法,使用 @Import() 在容器启动时向容器中注入一个 AnnotationAwareAspectJAutoProxyCreator 这是一个注解模式装配切面的自动代理创建器(注入过程了解@Import注入的几种方式)
- 分析 AnnotationAwareAspectJAutoProxyCreator 类的继承关系
AnnotationAwareAspectJAutoProxyCreator
---->|AnnotationAwareAspectJAutoProxyCreator
--------->|AbstractAdvisorAutoProxyCreator
--------------->|AbstractAutoProxyCreator
-------------------------->| ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
(其中 SmartInstantiationAwareBeanPostProcessor 又继承了 InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor又继承了BeanPostProcessor)
发现 AnnotationAwareAspectJAutoProxyCreator 间接实现了SmartInstantiationAwareBeanPostProcessor 与 BeanFactoryAware接口
注意点 SmartInstantiationAwareBeanPostProcessor 继承了InstantiationAwareBeanPostProcessor 继承了BeanPostProcessor,InstantiationAwareBeanPostProcessor 与BeanPostProcessor不同的是增加了一个 postProcessBeforeInstantiation(),抽象方法,这个方法是在被监管的bean创建前执行的,这些后置处理器相关的方法在 AnnotationAwareAspectJAutoProxyCreator 的父类 AbstractAutoProxyCreator 中进行了实现,并且 bean 初始化前执行的方法 postProcessBeforeInitialization() 没做任何操作,直接进行了返回
- AnnotationAwareAspectJAutoProxyCreator 间接实现了SmartInstantiationAwareBeanPostProcessor 后置处理器接口,该接口又继承自InstantiationAwareBeanPostProcessor接口,这个接口又继承了BeanPostProcessor接口,那么AnnotationAwareAspectJAutoProxyCreator 类就可以看为是一个后置处理器
- AnnotationAwareAspectJAutoProxyCreator 类间接实现 BeanFactoryAware 接口,在AbstractAutoProxyCreator父类中重写 了setBeanFactory()方法,获取容器中的 BeanFactory
- 根据继承关系由最上层父类开始查看,下级子类中是否重写了这两个接口中的抽象方法,下级子类的下级子类,是否有对这些方法再次进行了覆盖等,找到真实调用的那个
2.复习 Spring 容器启动后 bean 的注入执行过程,了解 AnnotationAwareAspectJAutoProxyCreator 的注入
- Spring 容器启动注入bean时,首先会将直接或间接继承 BeanPostProcessor 接口的 bean 创建 初始化,注入到容器中,Spring 默认提供了一个实现 BeanPostProcessor 接口的 ApplicationContextAwareProcessor 后置处理器,每个 bean 的创建都会被该后置处理器监控到,执行初始化bean之前要执行的方法postProcessBeforeInitialization(),在方法中调用 invokeAwareInterfaces() 方法,判断当前要创建的 bean 是否是 Aware 的直接子类或间接子类,如果是,在 调用这个 bean 重写的 Aware 中的抽象方法,获取 Spring 自己的组件赋值当前要创建的 bean 对象
- AnnotationAwareAspectJAutoProxyCreator 间接继承了 BeanFactoryAware 接口,在创建这个bean时,被ApplicationContextAwareProcessor 中的 invokeAwareInterfaces() 判断到,方法中调用重写BeanFactoryAware 接口中的 setBeanFactory() 方法获取 Spring 提供的 BeanFactory ,并且 AnnotationAwareAspectJAutoProxyCreator 间接继承了 BeanPostProcessor接口
- 自此 AnnotationAwareAspectJAutoProxyCreator 持有 BeanFactory 先一步注入到了 Spring容器中
3.通过 AnnotationAwareAspectJAutoProxyCreator 生成代理对象
此时 AnnotationAwareAspectJAutoProxyCreator 已经创建注入到了容器中,开始创建其它 bean
- Spring 创建 IOC 容器,在创建容器时调用 AbstractApplicationContext 中的 refresh() 方法刷新容器
- 在 refresh() 方法中首先调用 registerBeanPostProcessors()该方法首先向容器中注册所有继承了 BeanPostProcessor 的 bean(包括间接继承与直接继承,Spring 自己提供的,与自定义创建的,后续的创建bean对象的步骤与下面 finishBeanFactoryInitialization()方法中的相同) , 然后调用 finishBeanFactoryInitialization() 方法创建所有单例对象(BeanPostProcessor 以外的单实例对象?)
- 在finishBeanFactoryInitialization() 方法中会获取到一个ConfigurableListableBeanFactory 类型的对象beanFactory,通过这个对象默认调用它的实现子类 DefaultListableBeanFactory 中的 preInstantiateSingletons()方法
- 在DefaultListableBeanFactory 的 preInstantiateSingletons() 方法中会通过 while 循环调用AbstractBeanFactory的 getBean(beanName)方法, 在 getBean() 方法中调用 doGetBean() 方法中会通过 getSingleton() 方法去获取 bean, 如果首次执行时,没有这个 bean, 则调用AbstractAutowireCapableBeanFactory 子类实现的 createBean() 方法,在createBean()方法中通过调用 doCreateBean()
- .createBean()方法中在调用doCreateBean()方法以前首先会调用 resolveBeforeInstantiation(beanName, mbdToUse); 通过后置处理器,创建当前 ben 的代理对象返回
- doCreateBean() 方法中首先调用会调用 populateBean() 方法, 对创建的 bean 的属性赋值 ,然后调用 initializeBean() 方法,执行创建这个 bean 的初始化方法
- initializeBean() 方法中先后调用了三个主要的方法 :
- applyBeanPostProcessorsBeforeInitialization() 执行初始化前的方法,
- invokeInitMethods() 执行初始化方法,例如我们自定义的一些初始化方法,框架中定义的一些初始化方法
- applyBeanPostProcessorsAfterInitialization() 执行初始化后的方法
- 初始化前后的方法执行,主要是判断需要初始化的bean是否是 BeanPostProcessor 的实现子类,如果是,在初始化前,调用执行 postProcessBeforeInitialization() 方法, 在初始化后,调用执行 postProcessAfterInitialization() 方法
createBean() 方法源码:
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException var7) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var7);
}
Object beanInstance;
try {
//======通过后置处理器,创建 当前需要创建的 bean 的代理对象并返回================
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
//==========================================================================
if (beanInstance != null) {
return beanInstance;
}
} catch (Throwable var8) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var8);
}
//=============创建 bean ===============
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
//======================================================
if (this.logger.isDebugEnabled()) {
this.logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
resolveBeforeInstantiation() 方法源码: 在调用createBean() 创建 bean 对象时,首先调用该方法,通过该方法创建 当前 bean 的代理对象注入到容器中
在 resolveBeforeInstantiation() 方法中调用了: applyBeanPostProcessorsBeforeInstantiation()
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = this.determineTargetType(beanName, mbd);
if (targetType != null) {
bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = bean != null;
}
return bean;
}
- applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);该方法会获取容器中所有后置处理器,遍历判断获取到的后置处理器是否有 InstantiationAwareBeanPostProcessor 类型的,如果有获取该后置处理器,调用创建 ben 对象前要执行的方法 postProcessBeforeInstantiation(beanClass, beanName); 方法,通过该方法创建出当前要创建的 bean 的代理类对象并返回
- AOP 中 通过 @EnableAspectJAutoProxy 向容器中注入的 AnnotationAwareAspectJAutoProxyCreator 间接继承了 InstantiationAwareBeanPostProcessor 接口,判断通过,执行 postProcessBeforeInstantiation() 方法
postProcessBeforeInstantiation() 后置处理器中,创建 bean 对象前自动执行的方法
- 判断要创建的bean 是否在 advisedBeans 中, advisedBeans中保存了所有要增强的bean
- 判断当前要创建的bean 是否是基础类型的,是否是切面类
- 判断是否需要跳过,shouldSkip() 调用的是AspectJAwareAdvisorAutoProxyCreator 中的,什么时候需要跳过,例如创建的bean是通知方法包装的增强器时…
自己理解
该方法中对于AOP 相关的并没有什么实际意义上的执行,只是进行了一些判断,如果判断不通过,将需要创建的bean存入advisedBeans集合中,并标识为false,不用增强,后续创建这个bean时,就不会对这个bean进行代理处理 - 当该方法执行完毕后,没有创建bean,createBean() 方法继续向下执行调用doCreateBean() 方法,调用目标类对象构造器,创建bean, 创建成功后,执行 AnnotationAwareAspectJAutoProxyCreator 中的 postProcessAfterInitialization()
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = this.getCacheKey(beanClass, beanName);
if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
//是否在 advisedBeans 中
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//是否是基础类型的,是否是切面 || 判断是否需要跳过
//当向advisedBeans中存储当前bean,并未false时,说明创建的这个bean不需要增强处理
if (this.isInfrastructureClass(beanClass) || this.shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
if (beanName != null) {
TargetSource targetSource = this.getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
this.targetSourcedBeans.add(beanName);
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = this.createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
}
return null;
}
postProcessAfterInitialization(); 后置处理器中,调用 bean 构造器,创建对象成功后,初始化 bean 后自动执行的方法
(初始化前执行的方法,在 AOP 相关设计中没做任何操作)
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
//判断是否已经代理过了
if (!this.earlyProxyReferences.contains(cacheKey)) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
//判断是否是已经在advisedBeans中集合中,该集合中存放了被标识为不用增强的和已经增强过的bean
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
//判断是否是切面类
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
//获取当前 bean 可以使用的增强器也就是通知方法,并根据前置通知,后置通知...对增强器进行排序(通过切入点匹配监管当前bean的通知方法)
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
//记录当前bean 已被增强处理
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建当前 bean 的代理对象
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
protected Object createProxy(Class<?> beanClass, String beanName, 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 (this.shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
this.evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//获取监管当前bean的所有增强器通知方法
Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
Advisor[] var7 = advisors;
int var8 = advisors.length;
for(int var9 = 0; var9 < var8; ++var9) {
Advisor advisor = var7[var9];
//将增强器保存到代理工厂中
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
this.customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (this.advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//获取代理对象
return proxyFactory.getProxy(this.getProxyClassLoader());
}
创建代理类
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
//JDK 动态代理
return new JdkDynamicAopProxy(config);
} else {
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.");
} else {
//Cglib 动态代理 ObjenesisCglibAopProxy(config)
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
在执行目标方法时,获取目标方法的所有增强器通知方法,将增强器包装为 MethodInterceptor 拦截器链,然后使用拦截器链,与目标方法中包含的数据,执行时在代理类中获取所有拦截器,判断是否有拦截器,是否该执行目标方法,如果没有拦截器,或执行到了目标方法位置,通过反射,执行目标方法,如果有拦截器,执行拦截器
三. AOP 总结
AOP 的搭建步骤
- Spring 中引入 AOP 相关依赖
- Spring 设置开启 AOP
- 创建 AOP 切面类,将界面类注入到容器中
- 切面类中编写通知方法
- 设置切入点,将通知方法织组目标方法
AOP 原理
- 通过 @EnableAspectJAutoProxy 注解设置 Spring 开启 AOP 了解到,在使用 AOP 时,会向 Spring 容器中注入一个AnnotationAwareAspectJAutoProxyCreator 后置处理器, AnnotationAwareAspectJAutoProxyCreator 间接实现了 InstantiationAwareBeanPostProcessor 与 BeanFactoryAware 接口,
InstantiationAwareBeanPostProcessor 又继承了 BeanPostProcessor 接口,与 BeanPostProcessor 不同的是,该接口中增加了一个 postProcessBeforeInstantiation() 抽象方法, 该方法是监控在创建bean以前执行的 - 分析 AnnotationAwareAspectJAutoProxyCreator 间接实现 BeanFactoryAware 接口, 是为了拿到 Spring 提供的BeanFactory ,因为 Spring 在提供容器时默认提供了一个 ApplicationContextAwareProcessor 后置处理器,注入到了容器中,在后续初始化 bean 时,都会被这个后置处理器监控到执行初始化的方法,判断当前要创建的 bean 是否是InstantiationAwareBeanPostProcessor 类型,如果是执行invoke() 方法,判断当前要创建的 bean 是否实现了某个 Aware 接口,如实现了,调用重写的该接口中的抽象方法获取, 获取Spring 提供的组件,此处获取的是 BeanFactory
- 分析 AnnotationAwareAspectJAutoProxyCreator 间接继承 InstantiationAwareBeanPostProcessor 接口,当前这个类就就是一个后置处理器,在该类的 AbstractAutoProxyCreator 父类中实现了后置处理器监控 bean 的创建前执行的方法,初始化前执行的方法与初始化后执行的方法
- Spring 容器在创建时调用 refresh() 方法刷新容器,方法中创建获取创建 bean 时,首先调用registerBeanPostProcessors() 方法,将直接或间接继承了 BeanPostProcessor 接口的 bean 创建注入到容器中,也就是 IOC 容器在创建注入 bean 时会首先创建注入后置处理器,然后调用 finishBeanFactoryInitialization() 方法创建其他所有单例对象,自此 AnnotationAwareAspectJAutoProxyCreator 这个后置处理器,就先一步获取到 BeanFactory 创建注入到了容器中
- 后续再创建其它 bean 时,在creatBean方法中(),首先会调用 resolveBeforeInstantiation(beanName, mbdToUse) 方法,获取所有后置处理器,循环判断是否存在InstantiationAwareBeanPostProcessor 这个类型的后置处理器 AnnotationAwareAspectJAutoProxyCreator 是该类型的实现子类,如果是调用执行创建 bean 以前的方法 postProcessBeforeInstantiation()
- postProcessBeforeInstantiation() 创建 bean 以前执行的方法 : 该方法在 AOP 相关的处理中并没有太多实际的动作,只是判断当前 bean 是否是切面类,是否是增强器(也就是切面类中的通知方法,在Spring 容器启动时,会将切面中的通知方法封装成一个个的增强器),是否允许被增强,如果不允许增强,将当前类放入一个集合中 advisedBeans,中并标识为false,不允许增强
- postProcessBeforeInitialization() 初始化 bean 以前执行的方法,该方法在此处没有任何操作,直接进行了返回
- postProcessAfterInitialization() 初始化 bean 后执行的方法,该方法中调用判断当前要创建的 bean 是否允许增强处理,是否已经被增强处理,创建ProxyFactory代理类工厂,通过切入点匹配获取监管当前 bean 的所有增强器(通知方法)将获取到的通知方法存入代理工厂中,通过 JDK 动态代理,或 Gglib 动态代理生成代理对象
- 执行 在执行目标方法时,获取目标方法的所有增强器通知方法,将增强器包装为 MethodInterceptor 拦截器链,如果有拦截器执行拦截器,如果没有通过反射执行目标方法?