【源码分析】Spring之AOP原理

Spring之AOP原理

首先看给容器中注册了什么组件,这个组件什么时候工作,这个组件的功能是什么?

(以@EnableAspectJAutoProxy为例:在容器中注册了AnnotationAwareAspectJAutoProxyCreator,然后再接着分析该组件的功能)

@EnableAspectJAutoProxy:开启基于注解的aop模式

所以从@EnableAspectJAutoProxy开始分析

Ⅰ、@EnableAspectJAutoProxy

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i7Uv23wX-1598325693450)(IMAGES/Snipaste_2020-08-17_21-33-12.png)]

  1. @Import(AspectJAutoProxyRegistrar.class):给容器中导入AspectJAutoProxyRegistrar

    • 利用AspectJAutoProxyRegistrar自定义给容器中注册beanDefinition;

    (给容器中注册一个AnnotationAwareAspectJAutoProxyCreator;)

    • key= internalAutoProxyCreator, value= AnnotationAwareAspectJAutoProxyCreator

    在AspectJAutoProxyRegistrar中执行:

    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    

    该方法调用以下方法:

    若registry中没有internalAutoProxyCreator,则创建该类的BeanDefinition,并将其放入registry中

    //AopConfigUtils
    //registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, null);
    
    private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
            //...
            //...
        } else {
            RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
            beanDefinition.setSource(source);
            beanDefinition.getPropertyValues().add("order", -2147483648);
            beanDefinition.setRole(2);
            registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
            return beanDefinition;
        }
    }
    

Ⅱ、AnnotationAwareAspectJAutoProxyCreator

AspectJ自动代理的创建器

1、分析

AnnotationAwareAspectJAutoProxyCrCeator

​ ->AspectJAwareAdvisorAutoProxyCreator

​ ->AbstractAdvisorAutoProxyCreator

​ ->AbstractAutoProxyCreator

​ implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

关注后置处理器(在bean初始化完成前后做事情)、BeanFactoryAware自动装配BeanFactory

-> :继承或实现

根据继承树从上往下分析:(找出与后置处理器、BeanFactory相关的方法并打上断点)

  1. AspectJAwareAdvisorAutoProxyCreator:
    • postProcessAfterInitialization
    • postProcessBeforeInstantiation
    • setBeanFactory
  2. AbstractAdvisorAutoProxyCreator
    • setBeanFactory 重写了父类的方法,不用再看父类的setBeanFactory
      • this.initBeanFactory((ConfigurableListableBeanFactory)beanFactory);
    • initBeanFactory
  3. AspectJAwareAdvisorAutoProxyCreator
    • 没有相关的方法
  4. AnnotationAwareAspectJAutoProxyCrCeator
    • initBeanFactory 重写

2、调试

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);

流程:

1.传入配置类(MainConfigOfAOP),创建ioc容器
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
    this.register(annotatedClasses);
    this.refresh();
}
2.注册配置类(register方法),调用refresh()刷新容器 --> 实例化所有bean
3.refresh()中调用invokeBeanFactoryPostProcessors(beanFactory):详见ioc源码
4.refresh()中调用registerBeanPostProcessors(beanFactory):注册bean的后置处理器来方便拦截bean的创建;

1、先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ngRw6P41-1598325693456)(IMAGES\Snipaste_2020-08-18_12-01-48.png)]

2、给容器中加别的BeanPostProcessor

3、优先注册实现了PriorityOrdered接口的BeanPostProcessor;

4、再给容器中注册实现了Ordered接口的BeanPostProcessor;

5、注册没实现优先级接口的BeanPostProcessor;

6、注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存在容器中;

创建internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】

  1. 创建Bean的实例

  2. populateBean;给bean的各种属性赋值

  3. initializeBean:初始化bean;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Al4YwGdx-1598325693459)(images\Snipaste_2020-08-18_12-43-00.png)]

​ 1) invokeAwareMethods():处理Aware接口的方法回调

​ 判断 bean instanceof BeanFactoryAware ===执行> setFactory方法 (结合第一步的分析来看)

​ 2) applyBeanPostProcessorsBeforeInitialization():获取并应用所有后置处理器的postProcessBeforeInitialization()

​ 3) invokeInitMethods();执行自定义的初始化方法

​ 4) applyBeanPostProcessorsAfterInitialization();获取并执行所有后置处理器的postProcessAfterInitialization();

​ 4. BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功;

7、把BeanPostProcessor注册到BeanFactory中;

  • beanFactory.addBeanPostProcessor(postProcessor);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WGriVOfv-1598325693465)(images\Snipaste_2020-08-18_13-10-49.png)]

//AbstractApplicationContext.class

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
//PostProcessorRegistrationDelegate

public static void registerBeanPostProcessors(
      ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

    //1. 先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor
   String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

   // Register BeanPostProcessorChecker that logs an info message when
   // a bean is created during BeanPostProcessor instantiation, i.e. when
   // a bean is not eligible for getting processed by all BeanPostProcessors.
   int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    //2. 给容器中加别的BeanPostProcessor
   beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

   // Separate between BeanPostProcessors that implement PriorityOrdered,
   // Ordered, and the rest.
   List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
   List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
   List<String> orderedPostProcessorNames = new ArrayList<String>();
   List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
   for (String ppName : postProcessorNames) {
      if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
         BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
         priorityOrderedPostProcessors.add(pp);
         if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
         }
      }
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
         orderedPostProcessorNames.add(ppName);
      }
      else {
         nonOrderedPostProcessorNames.add(ppName);
      }
   }

   // First, register the BeanPostProcessors that implement PriorityOrdered.
   //3. 优先注册实现了PriorityOrdered接口的BeanPostProcessor;
   sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

   // Next, register the BeanPostProcessors that implement Ordered.
   //4. 再给容器中注册实现了Ordered接口的BeanPostProcessor;
   List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
   for (String ppName : orderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      orderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         internalPostProcessors.add(pp);
      }
   }
   sortPostProcessors(orderedPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, orderedPostProcessors);

   // Now, register all regular BeanPostProcessors.
   //5. 注册没实现优先级接口的BeanPostProcessor;
   List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
   for (String ppName : nonOrderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      nonOrderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         internalPostProcessors.add(pp);
      }
   }
   registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

   // Finally, re-register all internal BeanPostProcessors.
   sortPostProcessors(internalPostProcessors, beanFactory);
   //6. 注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存在容器中
   registerBeanPostProcessors(beanFactory, internalPostProcessors);

   // Re-register post-processor for detecting inner beans as ApplicationListeners,
   // moving it to the end of the processor chain (for picking up proxies etc).
   //7. 把BeanPostProcessor注册到BeanFactory中;
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

第一大点 + 第二大点以上部分 == 创建和注册AnnotationAwareAspectJAutoProxyCreator的过程

AnnotationAwareAspectJAutoProxyCreator是 postProcessBeforeInstantiation 类型的后置处理器

注意区分:

postProcessBeforeInstantiation — > Instantiation 实例化

postProcessBeforeInitialization — > Initialization 初始化

5.refresh()中调用finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工作;创建剩下的单实例bean

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bA9kjryK-1598325693468)(IMAGES\Snipaste_2020-08-18_18-01-46.png)]

大体流程:

AbstractApplicationContext#getBean

-> AbstractBeanFactory#getBean

-> AbstractBeanFactory#doGetBean

-> DefaultSingletonBeanRegistry#getSingleton(String, boolean)

-> DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory<?>)

-> AbstractAutowireCapableBeanFactory#createBean

-> resolveBeforeInstantiation 或 doCreateBean

(有两次getSingleton)

1、遍历获取容器中所有的Bean,依次创建对象getBean(beanName);

2、创建bean doGetBean()

  1. 先从缓存中获取当前bean,如果能获取到,说明bean是之前被创建过的,直接使用,否则再创建;

    只要创建好的Bean都会被缓存起来

  2. createBean():创建bean;

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eDas6lu2-1598325693470)(C:\Users\0416\AppData\Roaming\Typora\typora-user-images\image-20200818233534235.png)]

    注意:

    • BeanPostProcessor是在Bean对象创建完成初始化前后调用的, 由4.6.3可知

    • InstantiationAwareBeanPostProcessor是在创建Bean实例之前先尝试用后置处理器返回对象的,由上图可知

    1. resolveBeforeInstantiation(beanName, mbdToUse);解析BeforeInstantiation

    希望后置处理器在此能返回一个代理对象;如果能返回代理对象就使用,如果不能就继续

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I9ezzn7F-1598325693472)(IMAGES\Snipaste_2020-08-18_23-57-09.png)]

    1. doCreateBean(beanName, mbdToUse, args);真正的去创建一个bean实例;和4.6流程一样;

结论:

AnnotationAwareAspectJAutoProxyCreator 实现了 InstantiationAwareBeanPostProcessor 因此在所有bean创建之前会有一个拦截,会调用postProcessBeforeInstantiation(),尝试返回bean的代理对象

接下来接着分析AnnotationAwareAspectJAutoProxyCreator的具体作用,postProcessBeforeInstantiation()做了什么事情

6.AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator【InstantiationAwareBeanPostProcessor】的作用:

1、每一个bean创建之前,调用postProcessBeforeInstantiation();

​ 关心MathCalculator(普通bean)和LogAspect(添加了@Aspcet)的创建(自定义的两个bean)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fbw1AQXr-1598325693474)(IMAGES\Snipaste_2020-08-19_10-04-33.png)]

(调试 beanClass = MathCalculator 的情况 :)

  1. 判断当前bean是否在advisedBeans中(保存了所有需要增强bean)

  2. 判断当前bean是否是基础类型的(实现Advice、Pointcut、Advisor、AopInfrastructureBean接口,或者是否是切面(使用了@Aspect))

  3. 是否需要跳过

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u7TEoV9G-1598325693476)(images\Snipaste_2020-08-19_00-47-57.png)]

​ 1) 获取候选的增强器(切面里面的通知方法)【List candidateAdvisors】

  • 每一个封装的通知方法的增强器是 InstantiationModelAwarePointcutAdvisor 类型的;

  • 判断每一个增强器是否是 AspectJPointcutAdvisor 类型的;返回true

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zitEh6YY-1598325693479)(IMAGES\Snipaste_2020-08-19_01-00-49.png)]

​ 2) 调用父类的shouldSkip ,永远返回false

2、创建对象 (执行new MathCalculator — bean的实例化过程(getBean、doCreateBean…))

3、对象创建完成之后调用:

postProcessAfterInitialization;

​ return wrapIfNecessary(bean, beanName, cacheKey); //包装如果需要的情况下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kZ24qjeM-1598325693480)(IMAGES\Snipaste_2020-08-19_01-22-00.png)]

  1. 获取当前bean的所有增强器(通知方法) Object[] specificInterceptors

    1. 找到候选的所有的增强器(找哪些通知方法是需要切入当前bean方法的)

    2. 获取到能在bean使用的增强器。

    3. 给增强器排序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jXXhP6ig-1598325693482)(IMAGES\Snipaste_2020-08-19_01-31-34.png)]

  1. 保存当前bean在advisedBeans中;

  2. 如果当前bean需要增强,创建当前bean的代理对象;

    1. 获取所有增强器(通知方法)

    2. 保存到proxyFactory

    3. 创建代理对象:Spring自动决定

    • JdkDynamicAopProxy(config); jdk动态代理;(bean实现了接口)
    • ObjenesisCglibAopProxy(config);cglib的动态代理;(没有实现接口)
  3. 给容器中返回当前组件(MathCalculator的实例)使用cglib增强了的代理对象;

  4. 以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J2xEy61S-1598325693485)(IMAGES\Snipaste_2020-08-19_01-41-00.png)]

小结:

AnnotationAwareAspectJAutoProxyCreator是一个InstantiationAwareBeanPostProcessor类型的后置处理器,它会在bean创建前后执行一些操作,特别是创建后会判断当前bean是否需要增强,若是则返回当前bean的代理对象

然后该代理对象执行方法利用拦截器链进行调用,因此接下来分析目标方法的执行过程:

7.目标方法执行

在目标方法上打上断点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jYKfgEM6-1598325693488)(IMAGES\Snipaste_2020-08-19_10-06-35.png)]

容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器,目标对象,xxx);

1、CglibAopProxy.intercept();拦截目标方法的执行

2、根据ProxyFactory对象获取将要执行的目标方法拦截器链;

//CglibAopProxy.intercept();

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  1. List interceptorList保存所有拦截器 length = 5

    一个默认的ExposeInvocationInterceptor 和 4个增强器;

  2. 遍历所有的增强器,将其转为Interceptor;

    Object[] = registry.getInterceptors(advisor);

  3. 在advisor instanceof PointcutAdvisor的情况下:

    将增强器转为List;

    如果是MethodInterceptor,直接加入到集合中

    如果不是,使用AdvisorAdapter将增强器转为MethodInterceptor;

    转换完成返回MethodInterceptor[];

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R9r4yB7d-1598325693490)(images\Snipaste_2020-08-19_11-48-28.png)]

3、如果没有拦截器链,直接执行目标方法;

​ 拦截器链(每一个通知方法又被包装为方法拦截器,利用MethodInterceptor机制)

4、如果有拦截器链,把需要执行的目标对象,目标方法,拦截器链等信息传入创建一个 CglibMethodInvocation 对象,并调用 :

Object retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6noYX2qC-1598325693492)(images\Snipaste_2020-08-19_11-37-26.png)]

小结:

在目标方法执行之前,会把增强器转化成拦截器,形成一个拦截器链,

然后根据该拦截器链创建一个CglibMethodInvocation 并调用 proceed()

接下来开始分析proceed方法的执行,即拦截器的触发过程:

5、拦截器链的触发过程;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W0V1CQe6-1598325693494)(IMAGES\Snipaste_2020-08-19_23-15-52.png)]

  1. 如果没有拦截器执行执行目标方法,或者 拦截器的索引 = 拦截器数组-1 (即执行到了最后一个拦截器)执行目标方法;

  2. 链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行;

    拦截器链的机制,保证通知方法与目标方法的执行顺序;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZwmPrz71-1598325693495)(IMAGES\Snipaste_2020-08-19_23-26-39.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WuK2zG6k-1598325693499)(IMAGES\Snipaste_2020-08-20_00-09-19.png)]

Ⅲ、总结

1、@EnableAspectJAutoProxy 开启AOP功能

2、@EnableAspectJAutoProxy 会给容器中注册一个组件 AnnotationAwareAspectJAutoProxyCreator

3、AnnotationAwareAspectJAutoProxyCreator是一个后置处理器;

4、容器的创建流程:

  1. registerBeanPostProcessors()注册后置处理器;创建AnnotationAwareAspectJAutoProxyCreator对象

  2. finishBeanFactoryInitialization()初始化剩下的单实例bean

  3. 创建业务逻辑组件和切面组件

  4. AnnotationAwareAspectJAutoProxyCreator拦截组件的创建过程

  5. 组件创建完之后,判断组件是否需要增强

    是:切面的通知方法,包装成增强器(Advisor);给业务逻辑组件创建一个代理对象(cglib);

5、执行目标方法:

  1. 代理对象执行目标方法
  2. CglibAopProxy.intercept();
    • 得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor)
    • 利用拦截器的链式机制,依次进入每一个拦截器进行执行;
    • 效果:
      • 正常执行:前置通知 --> 目标方法 --> 后置通知 --> 返回通知
      • 出现异常:前置通知 --> 目标方法 --> 后置通知 --> 异常通知
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值