Spring AOP源码

AOP是什么怎么用就不在这里赘述了,这里就从源码看一下AOP的实现。

1、Spring 如果要支持注解形式的AOP,就要在配置文件中配置<aop:aspectj-autoproxy/>。

这里简单说一下Spring解析标签的过程:Spring中将标签分为默认标签(import、alias,bean和beans)和自定义标签。

<aop:aspectj-autoproxy/>属于自定义标签,解析过程为当读取到这个标签时,会根据命名空间去找到对应的自定义标签处理器AopNamespaceHandler,AopNamespaceHandler会执行init()方法。在这里会将AspectJAutoProxyBeanDefinitionParser进行注册。而AspectJAutoProxyBeanDefinitionParser正是专门解析"aspectj-autoproxy"标签的解析器。

1

AspectJAutoProxyBeanDefinitionParser实现了BeanDefinitionParser接口,会执行parse()对标签进行解析。这个parse()中AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element)这个方法,从名字就可以看出是用来注册自动代理创建器,我们具体看下这个方法内做了什么。

2

一共做了三件事:

    1)注册或者升级AnnotationAwareAspectJAutoProxyCreator

    2)对于proxy-target-class以及expose-proxy 属性的处理

    3)注册组件并通知,便于监听器做进一步处理

3

1)注册或者升级AnnotationAwareAspectJAutoProxyCreator

   先看第一件,跟踪代码可依次走到如下两个方法。主要功能点就是注册AnnotationAwareAspectJAutoProxyCreator。

   具体注册过程,会先判断自动代理创建器是否已经存在。

        1)不存在,直接创建新的创建器。

        2)若存在

                1)且与想要创建的新创建器相同,不进行操作。

                2)且与想要创建的新创建器不同,就要判断两个创建器的优先级,如果新创建器优先级高,则进行新创建器的创建,否则不操作还是用原来创建器。

4
5

 2)对于proxy-target-class以及expose-proxy 属性的处理

     这个方法实际就是读取配置文件并将属性赋值的过程。


6

        说一下这个两个属性作用。

           1)proxy-target-class

            默认情况下,"proxy-target-class"默认是"false",当被代理类实现了至少一个接口,Spring默认使用JDK动态代理,当被代理类没有实现接口时使用CGLIB代理,但是如果想强制任何时候都使用CGLIB代理,那么需要如下配置:

                                

            2)expose-proxy

         如下例子可以说明这个属性。


有时候目标对象内部的自我调用将无法实施切面中的增强,此处的this 指向目标对象,因此调用this.b()将不会执行b事务切面,即不会执行事务增强。

为了解决这个问题,配置:

然后将以上代码中的“this.b()”修改为“ ((AService) AopContext.currentProxy()).b()”即可。

通过以上的修改便可以完成对a和b方法的同时增强。


 3)注册组件并通知,便于监听器做进一步处理

    这一步是注册组件,对于AOP实现没有什么关联。



2、在上面完成了AnnotationAwareAspectJAutoProxyCreator的注册创建,这个类也是实现AOP的关键,我们看这个类到底怎么实现的AOP。可以看到AnnotationAwareAspectJAutoProxyCreator类实现了BeanPostProcessor接口。

BeanPostProcessor常常被称为后置处理器,作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。流程如下:

Spring IOC容器实例化Bean--->调用BeanPostProcessor的postProcessBeforeInitialization方法--->调用bean实例的初始化方法--->调用BeanPostProcessor的postProcessAfterInitialization方法


AnnotationAwareAspectJAutoProxyCreator实现BeanPostProcessor 后,当Spring加载Bean时会在初始化后调用其父类AbstractAutoProxyCreator重写的postProcessAfterInitialization方法,对生产出的bean进行包装。

7

具体看下AbstractAutoProxyCreator重写的postProcessAfterInitialization方法,其中wrapIfNecessary()方法是我们要关注的。

8

看注释相信大家也大概明白这个方法的逻辑了,无非是先判断这个类是不是需要增强,如果需要增强就创建代理。这里我们主要看getAdvicesAndAdvisorsForBean()和createProxy()这两个方法。

9


1)getAdvicesAndAdvisorsForBean()


10

下面实际做了两件事,获取所有的增强器以及寻找所有增强器中适用于这个bean 的增强器。


11

我们先来看一下怎么获取的所有增强器。主要是分别获取了xml配置中的增强器和注解中的增强器。

12

我们主要看一下怎样获取注解形式的增强器,也就是buildAspectJAdvisors()这个方法,图片里有注释,简单来说就是拿到所有beanName,遍历beanName找到有@Aspect注解的类,然后处理这些有@Aspect注解的类的提取增强器。

13

提取增强器主要是getAdvisors()这个方法,我们接下来看下这个方法具体实现。

1)getPointcut()拿到切点信息

2)new InstantiationModelAwarePointcutAdvisorImpl()封装生成增强器。

14

1)getPointcut()拿到切点信息

切点信息获取其实也是获取方法上注解的信息,不详细解释了。

15

2)new InstantiationModelAwarePointcutAdvisorImpl()封装生成增强器。

可以看出来如果是懒加载,则先看到这可能还是不能看出来我们熟悉的内容,别急,往下看,看instantiateAdvice()方法。

16

我们可以看到before、after这些我们熟悉的切面注解了,spring会根据注解生成不同类型的增强器,常说的前置增强、后置增强、环绕增强。

17

至此我么我们知道了spring怎么获取所有的增强器。那么返回之前我们的地方。拿到所有增强器后,就是找出适用这个bean的增强器,其实就是找到符合我们配置的通配符的增强器。

18

至此我们分析完了获取这个类增强器的方法。如果这个类存在需要增强器,就要创建代理,也就是createProxy()。

19

这个方法就为我们创建了代理类,当实际调用时是代理类替代目标类为我们执行了方法,当然就把我们的切面方法也执行了。

20

















BeanPostProcessor

你可能感兴趣的:(Spring AOP源码)