基于注解式的SpringAOP源码解析-5-AnnotationAwareAspectJAutoProxyCreator如何创建AOP代理对象
AnnotationAwareAspectJAutoProxyCreator如何创建AOP代理对象
回顾上一篇
上一篇讲解了AnnotationAwareAspectJAutoProxyCreator的执行时机,它是在普通bean的创建过程中,尝试创建一个bean的代理对象替代bean去注册到容器中。这个尝试过程首先调用了postProcessBeforInstantiation方法。这一篇开始讲解这个方法,并往下调试分析aop代理对象的创建过程。
调试观察aop代理对象是如何创建的
由于前面写的MathCalculator这个bean是需要aop代理的bean,因此我们就以MathCalculator为例来分析这个bean的创建过程。
1,进入postProcessBeforInstantiation
这里首先判断当前bean是否已经在已增强的advisedBeans集合中,如果已经在了,则直接返回null,不需要再创建了。显然,我们当前的bean调试到这里肯定是还没有增强的,因此不在这个集合中。
接下里则是判断当前bean是否是基础类型或者是有切面注解(这里所谓的基础类型,下一张源码分支图将会解释)。
然后判断当前bean是否要被跳过,shouldSkip(下一张源码分支图将会解释)
最终当前MathCalculator这个对于上述的那些判断都是返回false,因此最后这个方法返回null。
1)进入isInfrastructureClass(postProcessBeforInstantiation的源码分支)
这里方法是判断当前bean是否属于基础类型并且是否属于@Aspect注解,这里首先调用了父类的方法(进入下一张分支图分析)。接着调用了isAspect方法(进入下一张分支图分析)
进入父类的isInfrastructureClass(isInfrastructureClass的源码分支)
父类的isInfrastructureClass方法,判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean。而我们当前的bean并不属于上述的。因此这个方法返回false。
进入isAspect(isInfrastructureClass的源码分支)
判断当前是否是Aspect注解,而我们当前bean不是,因此这里也返回false。
2)进入shouldSkip(postProcessBeforInstantiation的源码分支)
这个方法首先获取所有候选的增强器,我们可以看到下图右侧的红框的内容,增强器其实就是我们定义了的那些切面通知方法。
接着判断这些候选增强器是否属于AspectJPointcutAdvisor,如果是直接返回true,代表需要跳过。而下图左侧红框的内容可以看出当前的候选增强器属于InstantiationModelAwarePointcutAdvisor,因此这里直接调用了父类的shouldSkip方法,而父类的这个方法直接返回false,因此当前的shouldSkip最终返回了false。
2,普通bean的正常创建
通过上述分析,postProcessBeforInstantiation方法最终返回了null,没有拿到代理对象,通过上一篇的分析,继续调试将会来到
正常的创建bean的过程doGetBean,而这个方法的过程我们在前一个章节也分析过了。会在执行bean的初始化方法的前后执行所有BeanPostProcessor后置处理器的方法。而我们的AnnotationAwareAspectJAutoProxyCreator就是一个BeanPostProcessor,因此最终也会执行到它的postProcessBeforeInitialization,postProcessAfterInitialization这个两个方法。因此我们继续调试来到AnnotationAwareAspectJAutoProxyCreator父类的这个两个方法分析。
3,进入postProcessAfterInitialization
这里我们可以看到postProcessBeforeInitialization没有对bean做任何修饰直接返回了当前bean。
而postProcessAfterInitialization方法则执行了一个warpIfNecessary方法,表示如何必要的方法进行包装,这里我们进入源码观察
4,进入warpIfNecessary
这里首先获取bean可用的增强器(获取的方法后面的图有源码分支解释),可以看到最终的可用的增强器如下图红框所示。
接着判断如果当前bean有可用的增强器,则将当前bean的key放进以增强的advisedBeans集合(这个集合我们在前面也分析了),并且创建bean的代理对象(创建的方法后面的图有源码分支解释),
最终返回了这个代理对象。
1)获取bean可用的增强器(warpIfNecessary的源码分支)
先获取所有的候选增强器,然后筛选出可以应用到当前bean的增强器(筛选的过程可以自行查看源码,里面就是对切入点表表达式的一些判断),最后给这些增强器排序。
2)进入createProxy(warpIfNecessary的源码分支)
创建代理工厂
这里首先新建一个代理工厂,接着将bean所有的增强器加入到这个工厂中,然后调用工厂的getProxy方法。
调用getProxy方法经历了以下方法调用栈,最终来到了createAopProxy方法。
创建AOP代理对象
如果目标bean是有实现接口的或者本身即是一个代理对象,就使用jdk动态代理的方式获取代理对象,
否则使用cglib动态代理的方式获取代理对象
下一篇预告
这一篇主要讲解AnnotationAwareAspectJAutoProxyCreator是否如何创建AOP代理对象的,讲了postProcessBeforInstantiation方法的一系列判断最终返回了null,接着bean的创建来到了普通的doCreateBean过程,因此会走BeanPostProcessor的两个方法,因此最终来到了AnnotationAwareAspectJAutoProxyCreator父类的postProcessBeforeInitialization和postProcessAfterInitialization两个方法,在postProcessAfterInitialization方法中,最终去创建了AOP代理对象,因此最终bean的创建实际上创建的是bean的AOP代理对象。下一篇我们将会讲解AOP代理对象在执行bean的目标方法时,是如何执行的。