四、spring之AOP

   上一节对doGetBean()方法为入口,进行bean的注册、实例化、属性赋值等操作进行了说明。本章内容主要是针对前置、后置处理进行说明,主要围绕AOP进行理解。

先认识下面3个方法:

applyBeanPostProcessorsBeforeInstantiation:前置处理器实例化

applyBeanPostProcessorsAfterInitialization:后置处理器初始化

applyBeanPostProcessorsBeforeInitialization:前置处理器初始化


其中在AbstractAutowireCapableBeanFactory.resolveBeforeInstantiationy用到了applyBeanPostProcessorsBeforeInstantiation、applyBeanPostProcessorsAfterInitialization。

在AbstractAutowireCapableBeanFactory.initializeBean用到了applyBeanPostProcessorsAfterInitialization、applyBeanPostProcessorsBeforeInitialization


   因为这3个方法在不同的地方都被调用过,而且Aop与这几个方法密切相关。总的来说:

   applyBeanPostProcessorsBeforeInstantiation,会被调用,基本上用处不大,逻辑也不复杂。该方法跟后置方法很类似。

      applyBeanPostProcessorsBeforeInitialization,也是会被调用,基本上用处不大,逻辑也不复杂。

   applyBeanPostProcessorsAfterInitialization,如果实现了aop之后,被代理的类在这个方法中还是挺复杂的。可以以这个方法为一个研究点(打个断点)。


对于一个普通bean来说,初始化流程是(主要的逻辑在AbstractAutowireCapableBeanFactory.doCreateBean()方法里面):

由RootBeanDefinition封装为beanWrapperImpl,然后实例化createBeanInstance(),然后属性赋值populateBean(), 前置初始化bean(比如为aware的bean设置context),然后执行invokeInitMethods,执行初始化方法,然后后置初始化bean(与前置一样,只是方法不同)。

没有被aop代理的类不会执行到wrapIfNecessary()方法的查找增强型方法那里去。比如判断是否是增强的bean,是否有@aspenct注解的,是否在该类中寻找到了需要切入的方法。执行器BeanPostProcessor不会进入该方法,因为他本身就是执行器调入的方法。有@aspenct注解的会提前返回bean,没有需要切入方法的bean因为找不到advise,也不会被代理。


首先在总调度refresh()中的registerBeanPostProcessors()方法中会对实现了BeanPostProcessor接口的方法进行初始化。比如aop默认名“org.springframework.aop.config.internalAutoProxyCreator”,AnnotationAwareAspectJAutoProxyCreator类进行实例化。这个实例化跟普通的bean实例化没有区别。只是比普通的bean提前实例化了。

添加了@Aspect注解的bean类实例化也跟普通类没有什么区别。

但是被代理的bean实例化会复杂点。

1查找有注解@Aspect的类(这个是在applyBeanPostProcessorsBeforeInstantiation)查找的。

[if !supportLists]2   [endif] 根据注解pointcut\after\before\around获取增强器。

每个方法对应一个增强类。

[if !supportLists]3   [endif] 用cglib创建代理类。

cglib设置了superclass即被代理的类之后,就需要设置setCallback回调类,这个类需要实现MethodInterceptor接口。


   配置了Aop注解之后,首先是怎么去得到这些切入方法的呢?

在applyBeanPostProcessorsBeforeInstantiation方法中,其实去获取这些切入方法是比较隐蔽的。在一个判断是否直接返回bean的方法shouldSkip()中进行的。查找需求切入的方法如下:

[if !supportLists]1、      [endif]在beanfactroy中提取到所有的bean,然后找到有注解的@aspect的类

[if !supportLists]2、      [endif]根据事先预设好的@before\@after\@around等注解的找到代理方法,当然这里要做一些判断,比如要判断是否有pointcut,切入方法跟需要代理的方法是否一致等等。

[if !supportLists]3、      [endif]在对bean进行实例化时,会对每个bean进行判断,判断该类是否需要aop增强,根据找到的需要切入的方法进行匹配,看该类是否有该方法。判断的过程是比较复杂的。

[if !supportLists]4、      [endif]根据注解方法,每个方法都生成一个对应的增强类:

InstantiationModelAwarePointcutAdvisorImpl这个类里面也对应了AbstractAspectJAdvice增强类。因为before\after\around等都对应一个增强类。比如AspectJAfterAdvice、AspectJMethodBeforeAdvice等等方法。这些类的调用顺序在后面代理的类执行的时候是设定好的。

那么其实每个切入的方法都对应了一个InstantiationModelAwarePointcutAdvisorImpl这样的advise类,然后最后生成的代理类也是用到了这些类。


   对应代理类的生成用到的是cglib,底层用的是asm,这个框架在后面专门说明。这些框架技术只是固定的模式。

   spring用cglib生成的代理类,最重要的一步其实就是生成callback接口的实现类,MethodInterceptor接口也是继承的这个类。 spring用的内部类DynamicAdvisedInterceptor实现的这个类。之前的增强类InstantiationModelAwarePointcutAdvisorImpl被以数组的方式赋值到advised里面。   实现了MethodInterceptor之后,会被调用intercept()方法。这里使用的ReflectiveMethodInvocation.proceed  调用链,

interceptorsAndDynamicMethodMatchers按照数组调用,设计的很巧。而且顺序是固定的。虽然AspectJAfterAdvice.invoke方法最先被调用,但是after方法是在finally块最后被调用的。


每个切入点方法都会对应一个增强类,获取到了代理类实例之后,采用反射的方式获取到对象的方法:object.getClass().getMethod(),method.invoke(object)去执行方法。

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

推荐阅读更多精彩内容