四、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)去执行方法。

你可能感兴趣的:(四、spring之AOP)