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代理,那么需要如下配置:

                                <aop : aspectj-autoproxy    proxy-target-class="true"/>

            2)expose-proxy

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


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

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

<aop:aspectj-autoproxy expose-proxy=”true”/>

然后将以上代码中的“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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容