基于注解的AOP实现源码跟踪

1、@EnableAspectJAutoProxy实现功能分析

直接点开EnableAspectJAutoProxy的源码,可以看到在EnableAspectJAutoProxy类上通过注解@Import导入了一个组件AspectJAutoProxyRegistrar。
这里写图片描述

在EnableAspectJAutoProxy接口中,通过@Import向容器添加了新的组件AspectJAutoProxyRegistrar,它实现了接口:ImportBeanDefinitionRegistrar接口:
这里写图片描述
通过上述步骤,最终会在Spring容器中注入Bean:org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator。

2、AnnotationAwareAspectJAutoProxyCreator继承关系

这里写图片描述

从上类继承图可知AnnotationAwareAspectJAutoProxyCreator由于继承的关系,所以它是一个是一个后置处理器,并且实现了BeanFactoryAware接口。
在抽象类AbstractAutoProxyCreator第一次实现了BeanPostProcessor和BeanFactoryAware接口,然后又再AbstractAdvisorAutoProxyCreator重写了AbstractAutoProxyCreator的setBeanFactory接口,并在内部定义了initBeanFactory方法,setBeanFactory方法中调用initBeanFactory方法:
这里写图片描述
AnnotationAwareAspectJAutoProxyCreator又重写了父类AbstractAdvisorAutoProxyCreator它的initBeanFactory方法

3、AnnotationAwareAspectJAutoProxyCreator后置处理器的创建过程

这里写图片描述
debug调试图第14行:首先创建了一个AnnotationConfigApplicationContext容器
debug调试图第12行:进入AbstractApplicationContext.refresh()方法,此方式是spring启动的核心方法,spring容器初始化绝大部分核心方法都在此方法中调用。
这里写图片描述
debug调试图第11行:准备对容器中后置处理器Bean进行注册registerBeanPostProcessors
debug调试图第10行:此处是后置处理器的实现,将所有定义的后置处理器Bean注册到容器中。
在spring内部,将后置处理器划分为多个不同级别:
PriorityOrdered级别:实现了PriorityOrdered接口的后置处理器, PriorityOrdered实现了Ordered接口
Ordered级别:实现了Ordered接口的后置处理器
nonOrdered级别:普通的后置处理器
internal级别:内部后置处理器
这里写图片描述
注册顺序是PriorityOrdered> Ordered> nonOrdered>internal
这里写图片描述
debug调试图第9行:通过beanFactory.getBean()方法获取后置处理器Bean的实例,第一次获取的时候实例肯定为空,所有需要创建一个Bean实例。
debug调试图第4行:调用AbstractAutowireCapableBeanFactory.doCreateBean()方法创建Bean实例
这里写图片描述
从红色方框代码中可以看出,当一个Bean为单例时,创建的操作是从Bean工厂的缓存中直接移除Bean实例,但是实例并没有被丢弃,而是将实例有赋值到instanceWrapper继续使用。当instanceWrapper为空时,创建Bean的实例。

当Bean实例被创建完成后将调用populateBean方法,为bean实例的属性赋值(调用setter方法)。
这里写图片描述
在populateBean方法中,如果spring容器注册了InstantiationAwareBeanPostProcessor接口,那么InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()和InstantiationAwareBeanPostProcessor. postProcessPropertyValues()都将在此方法中调用。
这里写图片描述
populateBean方法执行完之后,将执行initializeBean方法,后置通知的所有方法将在此方法内部调用。
这里写图片描述
在代码1615行,首先会检测Bean是否实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口,如果实现了则调用对应的接口。
这里写图片描述
之后在1620和1633行处,分别调用了后置处理器的before和after方法。而在这两行代码之间则调用了bean的初始化方法,对bean进行初始化。

由于AnnotationAwareAspectJAutoProxyCreator实现了BeanFactoryAware接口,所以当调用setBeanFactory是,由于setBeanFactory被AbstractAdvisorAutoProxyCreator重写了,调用setBeanFactory实际被调用的是AbstractAdvisorAutoProxyCreator.setBeanFactory()方法,而在此方法的内部又调用的initBeanFactory方法,最终由于AnnotationAwareAspectJAutoProxyCreator重写了initBeanFactory方法,所以代码进入到AnnotationAwareAspectJAutoProxyCreator. initBeanFactory()方法中
这里写图片描述
在完成后续相关初始化工作后,将后置处理器注册到容器中,完成了后置处理器的注册过程。
这里写图片描述

4、被代理对象创建过程

这里写图片描述
debug调试图第17行:spring容器初始化剩余的普通Bean
这里写图片描述
AbstractApplicationContext.refresh()方法中,调用finishBeanFactoryInitialization()完成剩余的Bean初始化功能,经过前面的postProcessBeanFactory()方法,AnnotationAwareAspectJAutoProxyCreator后置处理器已经注册到了容器中,此时初始化Bean是,AnnotationAwareAspectJAutoProxyCreator可以对新创建的Bean进行操作。

debug调试图第10行:AnnotationAwareAspectJAutoProxyCreator实现了InstantiationAwareBeanPostProcessor和BeanPostProcessor两个后置处理器接口。所以每一个Bean被实例化之前,都会调用InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation()方法。
这里写图片描述
在resolveBeforeInstantiation方法内将调用所有实现了InstantiationAwareBeanPostProcessor接口的后置处理器,尝试使用后置处理器来创建一个代理对象,用于替换实际应该创建的Bean对象。
此处需要了解InstantiationAwareBeanPostProcessor和BeanPostProcessor两种类型的后置处理器区别:
InstantiationAwareBeanPostProcessor:将在对象实例化之前调用
BeanPostProcessor:在对象实例化之后,初始化方法之前后调用

debug调试图第9行:代码再次进入到初始化Bean的方法中,bean的代理对象创建实际上就是在BeanPostProcessor的接口方法postProcessAfterInitialization的实现中完成的。
这里写图片描述

debug调试图第5行:进入到AbstractAutoProxyCreator.wrapIfNecessary()方法中
在执行创建代理对象之前,首先将bean的id方法到advisedBeans集合中,此集合保存了容器中所有已经被增强后bean的id。
这里写图片描述
进入到createProxy方法,首先检查需要被创建代理的bean是否实现了接口,如果没有实现接口则会设置代理工厂为类代理。
这里写图片描述
从所有增强器中获取所有当前bean可以使用的增强器
这里写图片描述
跟踪代码进入到DefaultAopProxyFactory.createAopProxy()方法中,完成代理对象的创建。
这里写图片描述
代码红框处获取之前检测被代理bean的接口接口,如果实现了接口,则使用JDK动态代理,否则将使用Cglib创建代理对象。
到此,代理对象的创建过程基本完成。

5、代理对象方法执行

对象被代理后,代理对象中将保存了代理相关的全部的信息,主要包括增强器、目标对象等。
这里写图片描述
当代理对象执行被AOP拦截的方式时,会被CglibAopProxy.DynamicAdvisedInterceptor. intercept方法拦截。
这里写图片描述
this.advised实际上就是一个代理工厂,根据它获取到需要执行的目标方法的拦截器链。在获取拦截器链过程中,如果获取到的Advice没有实现MethodInterceptor接口,则需要使用对应的适配器将Advice适配成MethodInterceptor接口。
这里写图片描述
获取完拦截器链后,如果没有拦截器链则直接执行目标方法。如果有则把需要执行的目标对象、目标方法、拦截器链等信息传入创建一个 CglibMethodInvocation 对象,并调用 proceed()方法。
这里写图片描述
在前面获取到拦截器链时,拦截器链中如果有多个方法拦截器,那么他们的在List中的排序始终是固定的:默认拦截器->异常拦截器(异常通知)->返回拦截器(返回通知)->后置拦截器(后置通知)->前置拦截器(前置通知)
这里写图片描述
ExposeInvocationInterceptor为默认的,剩余4个是通知增强器。
在CglibMethodInvocation.proceed()方法中,首先判断如果拦截器链长度为0或者当前已经将所有拦截器递归调用完成,那么通过反射调用目标方法。否则通过自增currentInterceptorIndex的值,从拦截器链中逐个得到拦截器;然后以当前CglibMethodInvocation实例作为参数,传入方法拦截器的invoke方法中;最后在方法拦截器的方法中再次调用CglibMethodInvocation.proceed()。这样变形的递归调用,最终将会遍历完所有的方法拦截器,然后执行完成。
这里写图片描述
代理对象的方法执行过程中,拦截器链的执行过程大致如下:
这里写图片描述
1、 第一次进入CglibMethodInvocation.proceed方法时,currentInterceptorIndex默认为-1,所以自增之后为0,从拦截器链中获取到第一个拦截器ExposeInvocationInterceptor,执行它的invoke方法。
2、 在ExposeInvocationInterceptor的invoke方法中又一次调用CglibMethodInvocation.proceed方法,此时currentInterceptorIndex值为0,自增之后为1,从拦截器链中得到第二个拦截器AspectJAfterThrowingAdvice,然后执行AspectJAfterThrowingAdvice的invoke方法。
3、 在AspectJAfterThrowingAdvice的invoke方法中,再次调用CglibMethodInvocation.proceed方法,此时currentInterceptorIndex值为1,自增之后为2,从拦截器链中得到第三个拦截器AfterReturningAdviceInterceptor,然后执行AfterReturningAdviceInterceptor的invoke方法。
4、 在AfterReturningAdviceInterceptor的invoke方法中,再次调用CglibMethodInvocation.proceed方法,此时currentInterceptorIndex值为2,自增之后为3,从拦截器链中得到第四个拦截器AspectJAfterAdvice,然后执行AspectJAfterAdvice的invoke方法。
5、 在AspectJAfterAdvice的invoke方法中,再次调用CglibMethodInvocation.proceed方法,此时currentInterceptorIndex值为3,自增之后为4,从拦截器链中得到第五个拦截器MethodBeforeAdviceInterceptor,然后执行MethodBeforeAdviceInterceptor的invoke方法。
6、 在MethodBeforeAdviceInterceptor的invoke方法中,首先执行前置通知方法,然后调用CglibMethodInvocation.proceed方法。此时在proceed方法中,已经遍历完所有的拦截器,所以currentInterceptorIndex值等于拦截器链的size-1,if条件判断满足,所以通过反射方法执行目标对象的目标方法。
这里写图片描述
7、 执行到此时,目标方法和前置通知已经执行完成,现在会返回到AspectJAfterAdvice中,执行后置通知方法;然后如果没有发生异常就返回到AfterReturningAdviceInterceptor拦截器中,执行返回通知;如果执行目标方法的时候发生了异常,则不会执行返回通知,而是抛出异常,同时异常被AspectJAfterThrowingAdvice捕获到,并执行异常通知,整个代理方法执行流程完成。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值