目录
AOP整体解析
AOP开启注解:@EnableAspectJAutoProxy
@EnableAspectJAutoProxy
导入了AspectJAutoProxyRegistrar
注册器,它实现了ImportBeanDefinitionRegistrar
接口,能够向Bean定义信息中心注册组件定义信息- 通过
ConfigurationClassPostProcessor
后置处理器可以解析@Import
注解从而导入AnnotationAwareAspectJAutoProxyCreator
组件,这个组件本质上就是一个Bean后置处理器,他会干预到每个组件的创建环节,就是这个后置处理器完成了AOP的功能
AnnotationAwareAspectJAutoProxyCreator类图
AnnotationAwareAspectJAutoProxyCreator功能
他属于Bean的后置处理器,在getBean的时候干预进来
- 走到容器刷新12步的注册所有Bean后置处理器
registerBeanPostProcessors(beanFactory)
,通过getBean来创建此Bean后置处理器 - 通过对BeanFactoryAware接口的setBeanFactory方法封装,对BeanFactory进行处理
- 在初始化期间创建了
ReflectiveAspectJAdvisorFactory
增强工厂和BeanFactoryAspectJAdvisorsBuilderAdapter
建造者 - AnnotationAwareAspectJAutoProxyCreator创建完成之后,拦截判断每个其他的类是否有@Aspect注解,有就表示当前类是切面,再判断当前类是否要跳过,当前类是否是需要增强的Bean,不需要增强的话直接构建增强器
- 构建增强器,第一次进来不知道哪些组件是切面,获取所有的组件挨个判断是否切面,是的话就加入到切面的名称缓存集合中
增强器Advisor
他是spring找到所有切面的通知方法封装为Advisor,步骤如下
- 遍历所有的切面类
- 反射找到切面类的所有方法
- 每个方法判断是否通知方法(Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class,保存在ASPECTJ_ANNOTATION_CLASSES类数组中)
- 通知方法被封装为Advisor(增强器)
- 每个增强都是
InstantiationModelAwarePointcutAdvisorImpl
类型的实例
AOP对被切面类的代理过程
finishBeanFactoryInitialization(beanFactory)
,完成工厂的初始化开始创建所有的Bean,此步开始获取被切面类HelloService- 到第一处后置处理器,执行AOP后置拦截方法
AbstractAutoProxyCreator.postProcessBeforeInstantiation
- 判断是否是切面接口(肯定不是,现在都是注解方式)
- 判断是否跳过(获取到所有切面的所有增强器,看是否一些带有后缀的特殊类)
- 上一步什么都没做,直接返回的null,继续执行下面的流程,创建好了HelloService被切面对象,并执行
MergedBeanDefinitionPostProcessor
后置处理器,在执行属性的赋值,这两处AOP的后置处理器虽然介入了,但是它未进行任何的干预处理 - initializeBean初始化Bean方法,执行了
BeanPostProcessor.postProcessBeforeInitialization
(后置处理器的方法),此时AOP介入了,直接返回了原始对象本身,并未做代理操作 - 在执行
BeanPostProcessor.postProcessAfterInitialization
后置处理器方法,此时AOP真正开始干活了,去创建需要的代理对象
- 拿到所有的增强器,遍历挨个判断所有增强器的切入点正则是否能满足切入这个对象
- 像增强器数组中的第一位添加一个
ExposeInvocationInterceptor
(拦截器),在对增强器进行一些排序
- 还在上一步的方法中,AOP的后置处理器开始创建代理对象
- 创建代理对象,保存了
ProxyFactory
,这个工厂对象中保存了之前拿到的所有需要执行的Advisor
- 返回单例,HelloService的Bean创建完毕,此时实际上他属于一个代理对象
- AOP的准备工作到此已经全部完成,切面对象正常创建普通的Bean到单例池中
AOP原理总结图
AOP的运行流程
- 通过
CglibAopProxy
操作代理类,先把所有的增强器再转变为真正的方法拦截器MethodInterceptor
- 增强器只是保存了切面执行方法的一些信息,转为拦截器才能真正执行目标的方法
- 接下来是责任链的设计模式,在方法执行的前后执行对应的通知方法(构造成为了一个拦截器链list)
- 把构造好的链还有很多其他信息传进去,构造一个
CglibMethodInvocation
类,并调用它的proceed方法,在此步骤拦截器生效了 - 其内包含一个
currentInterceptorIndex
计数器,每调用一次拦截器的invoke方法拦截器其数值增加1,然后继续进入到下一个拦截器的invoke方法,层层嵌套下去,一直到所有的拦截器invoke方法执行,知道执行完前置通知的处理后,判断数组没有在需要执行的拦截器了,反射执行目标方法,最后在一层层的返回执行回去,其他拦截器的对应方法就也会得到执行(整个是一个链式结构的方法调用,俄罗斯套娃式)
执行原理示意图
拦截器和注解对应关系
MethodInterceptor
是Sping家的拦截器接口,就是为了把增强器都统一为拦截器接口,这样就有共同的方法,方便链式调用传递
分为五个拦截器,分别对应五个增强器
- ExposeInvocationInterceptor:ExposeInvocationInterceptor
- @Before:MethodBeforeAdviceInterceptor
- @AfterReturning:AspectJAfterReturningAdvice:异常情况下,返回通知就失败了
- @After:AspectJAfterAdvice:后置通知在异常情况下也能执行,因为他是在finally中执行的通知方法
- @AfterThrowing:AspectJAfterThrowingAdvice:他的invoke方法catch住了异常,然后执行自己的通知方法,执行完后再将异常抛出去
这三个Advice也都实现了拦截器接口
事件的机制
EventListenerMethodProcessor
事件用的后置处理器,两个执行的时机:
- 工厂后置处理环节执行增强:拿到所有
DefaultEventListenerFactory
类型的beanFactory实例,并将其进行一个排序在保存到eventListenerFactories属性之中 - 所有Bean都完全创建好后执行初始化(smart的后置处理器)
- 拿到容器中的所有组件,调用处理组件的
processBean(beanName, type)
方法 - 找到组件中所有
@EventListener
标注的方法,遍历找到的每一个方法 - 拿到
DefaultEventListenerFactory
,把当前方法,beanName等信息封装到ApplicationListenerMethodAdapter
适配器中 - 把此适配器(属于监听器)放到了容器中和事件派发器中
所以事件派发给的实际上是适配器,适配器再利用之前保存的Bean信息反射调用自己组件的事件监听方法
这个后置处理器给我们每一个监听方法都创建了一个适配器组件
事件发送
获取事件多波器中的所有的事件监听器,判断是否匹配,挨个遍历执行(观察者模式)
事件后置处理器类图
适配器类图
这个适配器实现了监听器的接口,本质上属于一个监听器,通过适配器的设计模式,引入了监听器的功能