Spring源码流程分析-AOP相关

根据Spring源码整理,其中Calculator为自定义的实现方法。

AnnotationConfigApplicationContext()加载配置类的流程

  1. register()传入配置类,准备IoC容器
  2. 注册配置类之后,refresh()刷新创建的容器
    1. invokeBeanFactoryPostProcessors()
    2. registerBeanPostProcessors()注册Bean的后置处理器以拦截bean
      1. 先获取IoC容器中已经定义了的需要创建的BeanProceesorNames
      2. 注册BeanPostProcessorChecker,该检查器在BeanPostProcessor实例化期间创建bean时记录信息消息,例如,当bean不符合所有BeanPostProcessor的处理条件时进行记录。
      3. 将BeanPostProcessor按照实现的PriorityOrdered,Ordered和其他接口进行分类
      4. 首先注册实现PriorityOrdered接口的BeanPostProccessor
      5. 然后注册实现了Ordered接口的BeanPostProccessor
        1. 根据PostProcessorName获取Bean

          1. 创建Bean实例(这里获取的是一个BeanWrap对象,并不是Bean)

            1. 给BeanPostProcessors返回一个代理对象替代目标bean实例的机会
            2. 真正创建Bean实例(PostProcessor本身也是一个Bean实例)
              1. 创建一个BeanWrapper(bean包装类)
              2. 创建Bean实例(输入internalAutoProxyCreator)
                1. 获取到真实的beanClass(这里是AnnotationAwareAspectJAutoProxyCreator)
                2. 如果没有特殊的处理,仅适用无参构造方法进行实例化
                  1. 先获取实例化的策略(通过getInstantiationStrategy()),用以实例化Bean

                    1. 使用CGLIB进行实例化(如果没有重写的情况下使用)
                    2. 使用反射机制进行实例化
          2. 通过BeanWrap获取包装的bean对象
          3. 通过BeanWrap获取包装的bean对象的类型
          4. 后置处理器可以修改合并的bean定义。
            1. 获取定义好的全部PostProcessor,如果有MergedBeanDefinitionPostProcessor处理器,则进行合并。(eg.合并了ApplicationListenerDetector)
          5. 给bean的各种属性赋值(populateBean)
          6. 初始化Bean(initializeBean)
            1. 调用Aware方法

              1. 对实现了BeanNameAware接口的bean进行设置beanName
              2. 对实现了BeanClassLoaderAware接口的Bean设置beanClassLoader
              3. 对实现了BeanFactoryAware接口的Bean设置beanFactory
            2. 在初始化前调用BeanPostProcessors处理器(applyBeanPostProcessorBeforeInitialization)
              1. 获取全部的BeanPostProcessors
              2. 依次执行其中的postProcessBeforeInitialization()方法
                1. 调用AwareInterface方法:
                2. ApplicationContextAwareProcessor时的AwareInterface方法如下:
                  1. EnvironmentAware->setEnvironment()
                  2. EmbeddedValueResolverAware->setEmbeddedValueResolver()
                  3. ResourceLoaderAware->setResourceLoader()
                  4. ApplicationEventPublisherAware->setApplicationEventPublisher()
                  5. MessageSourceAware->setMessageSource()
                  6. ApplicationContextAware->setApplicationContext()
            3. 调用Init方法:
              1. 先判断是否是InitializingBean(如果是,执行以下内容)
              2. 获取initMethodName
              3. 调用自定义的初始化方法
            4. 在初始化方法后调用BeanPostProcessors处理器(applyBeanPostProcesssorAfterInitialization)
        2. 判读并标记是否是InstantiationAwareBeanPostProcessor(实例化处理器)
        3. 判断并标记是否是DestructionAwareBeanPostProcessor(销毁处理器)
        4. 添加到BeanPostProccessor列表中
      6. 注册没有实现优先级接口的BeanPostProccessor
    3. 实例化剩下的非lazy-init单例(finishBeanFactoryInitialization->preInstantiateSingletons)
      1. 获取容器中全部的Bean名称
      2. 判断是否是FactoryBean,
      3. 如果不是FactoryBean直接获取创建Bean对象(getBeanName)
        1. 先检查单例缓存中是否存在手动注册的单例,(第一次创建单例,返回都是null)
        2. 创建bean实例
          1. 给BeanPostProcessors返回一个代理对象替代目标bean实例的机会

            1. 如果是InstantiationAwareBeanPostProcessor,就执行applyBeanPostProcessorsBeforeInstantiation。
          2. 然后调用doCreateBean()进行真实Bean的创建。

增强Calculator bean的流程

在refresh()->finishBeanFactoryInitialization中完成

  1. 实例化剩余的非懒加载的单例

    1. 获取全部的beanNames,循环遍历
    2. 获取bean定义(getBean(calculator))
      1. 先尝试从缓存中获取bean(第一次获取,为null)
      2. 标记bean已经被创建
      3. 获取bean依赖的bean并先进行创建(这里为null)
      4. 创建bean实例->createBean(beanName, mbd, args)
      5. 给BeanPostProcessors尝试返回代理对象的机会(resolveBeforeInstantiation)
        1. 进入Instantiation前置方法,执行前置处理器

          1. 获取全部的处理器,循环遍历,如果为InstantiationAwareBeanPostProcessor则调用前置处理器方法
          2. 当执行到AnnotationAwareAspectJAutoProxyCreator,执行器前置方法:
            1. 如果有自己定义的TargetSource则创建一个代理,这里为null(并没有起到实际的作用)
      6. doCreateBean()创建bean实例
        1. createBeanInstance()使用工厂方法(instantiateUsingFactoryMethod)调用Calculator构造方法,进行初始化构造

          1. 创建一个BeanWrapperImpl实现类
          2. 初始化BeanWrapperImpl(此时只包含默认值)
          3. 获取FactoryBeanName:cap10MainConfig
          4. 获取factoryBean:cap10MainConfig(被加强的)
          5. 当不使用任何factoryMethod和参数,尝试所有匹配给定参数的方法
          6. 获取全部符合条件方法(匹配到calculator())
          7. 如果只有一个符合条件的方法,将calculator()存入mdb.resolvedConstructorOrFactoryMethod
          8. instantiate()实例化bw bean装饰类
          9. 使用CGLIB的instantiate进行实例化
            1. 调用invoke()->intercept:cglibMethodProxy.invokeSuper->...->Calculator()构造函数
        2. 允许后置处理器修改合并的bean定义:applyMergedBeanDefinitionPostProcessors()
          1. 如果是MergedBeanDefinitionPostProcessor则执行其postProcessMergedBeanDefinition()
        3. populateBean给bean实例赋值
          1. 在配置属性前给InstantiationAwareBeanPostProcessors修改bean的机会,通过postProcessAfterInstantiation方法
          2. 检查如果实现了InstantiationAwareBeanPostProcessor,通过postProcessProperties获取PropertyValues
          3. applyPropertyValues应用属性值
        4. initializeBean():执行Bean初始化方法
          1. 调用Aware方法:invokeAwareMethods()(这里不存在Aware方法直接跳过)
          2. 调用Initialization前置处理器:applyBeanPostProcessorsBeforeInitialization()
            1. 获取全部的BeanPostProcessors,循环调用postProcessBeforeInitialization()--这里没做具体操作
          3. 调用初始化方法
            1. 判断bean类型是否是InitializingBean(这里跳过)
            2. 获取初始化方法
          4. 调用Initialization后置处理器
            1. 获取全部的BeanPostProces,循环遍历执行postProcessAfterInitialization()
            2. 如果需要,包装给定的bean,例如,当需要被代理。eg:当遇到AnnotationAwareAspectJAutoProxyCreator时,执行wrapIfNecessary():返回一个代理对象
              1. 创建代理

                1. 获取全部的拦截器
                2. 创建Proxy:
                  1. 构建增强器advisors
                  2. 添加到ProxyFactory
                  3. 创建Proxy(getProxy()->createAopProxy().getProxy()) 这里返回一个cglibaop代理
            3. 经过上一阶段的处理,返回的wrappedBean实际上变成了增强过后的代理对象,最终向上传递最后实际创建的是一个增强的代理对象。

AOP的调用流程

div(4, 1)入口:

  1. 进入拦截intercept()方法
  2. 获取TargetSource(包含Calculator)
  3. 获取目标类,target=targetSource.getTarget()
  4. 获取目标类对象类型
  5. 获取拦截链 getInterceptorsAndDynamicInterceptionAdvice()
    1. 尝试从缓存中获取方法列表
    2. 如果没有,则从advisorChainFactory中获取(getInterceptorsAndDynamicInterceptionAdvice())
    3. 获取advisors列表,并创建interceptorList
    4. 循环遍历advisors,如果类型为PointCutAdvisor进行处理:(如果匹配为真,则添加到interceptorsList中)
      1. 由advice获取拦截方法列表
      2. 添加到interceptorList列表中
    5. 添加到methodCache中
  6. 如果没有拦截器链直接执行目标方法
  7. 如果有,创建一个方法调用(CglibMethodInvocation(..).proceed())
    1. 链式获取每一个拦截器,执行每一个拦截器的invoke方法,该拦截器等待下一个拦截器返回以后再执行。

小结

@EnableAspectJAutoProxy

开启AOP功能:主要在容器中注入了一个组件AnnotationAwareAspectJAutoProxyCreator对象

简述流程

  1. registerBeanPostProcessors():注册后置处理器-其中创建了AnnotationAwareApectJAutoProxyCreator对象
  2. finishBeanFactoryInitialization():初始化剩余的单实例bean
    1. 创建业务逻辑和切面组件
    2. AnnotationAwareAspectJAutoProxyCreator:拦截组件的创建过程
    3. 判断组件是否需要增强,如果需要增强,返回一个代理对象
  3. 执行目标方法
    1. 代理对象执行目标方法
    2. CglibAopProxy.intercept()拦截
      1. 获取一个拦截链
      2. 利用链式拦截器,依次执行拦截器内方法
      3. 执行顺序:
        1. 正常:前置->目标方法->后置->返回通知
        2. 异常:前置->目标方法->后置->异常通知

Spring AOP部分源码分析的更多相关文章

  1. Spring AOP高级——源码实现(1)动态代理技术

    在正式进入Spring AOP的源码实现前,我们需要准备一定的基础也就是面向切面编程的核心——动态代理. 动态代理实际上也是一种结构型的设计模式,JDK中已经为我们准备好了这种设计模式,不过这种JDK ...

  2. Spring IOC 容器源码分析 - 余下的初始化工作

    1. 简介 本篇文章是"Spring IOC 容器源码分析"系列文章的最后一篇文章,本篇文章所分析的对象是 initializeBean 方法,该方法用于对已完成属性填充的 bea ...

  3. Spring IOC 容器源码分析 - 填充属性到 bean 原始对象

    1. 简介 本篇文章,我们来一起了解一下 Spring 是如何将配置文件中的属性值填充到 bean 对象中的.我在前面几篇文章中介绍过 Spring 创建 bean 的流程,即 Spring 先通过反 ...

  4. Spring IOC 容器源码分析 - 循环依赖的解决办法

    1. 简介 本文,我们来看一下 Spring 是如何解决循环依赖问题的.在本篇文章中,我会首先向大家介绍一下什么是循环依赖.然后,进入源码分析阶段.为了更好的说明 Spring 解决循环依赖的办法,我 ...

  5. Spring IOC 容器源码分析 - 创建原始 bean 对象

    1. 简介 本篇文章是上一篇文章(创建单例 bean 的过程)的延续.在上一篇文章中,我们从战略层面上领略了doCreateBean方法的全过程.本篇文章,我们就从战术的层面上,详细分析doCreat ...

  6. Spring IOC 容器源码分析 - 创建单例 bean 的过程

    1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...

  7. Spring IOC 容器源码分析 - 获取单例 bean

    1. 简介 为了写 Spring IOC 容器源码分析系列的文章,我特地写了一篇 Spring IOC 容器的导读文章.在导读一文中,我介绍了 Spring 的一些特性以及阅读 Spring 源码的一 ...

  8. Spring IOC 容器源码分析系列文章导读

    1. 简介 Spring 是一个轻量级的企业级应用开发框架,于 2004 年由 Rod Johnson 发布了 1.0 版本.经过十几年的迭代,现在的 Spring 框架已经非常成熟了.Spring ...

  9. 九、Spring之BeanFactory源码分析(一)

    Spring之BeanFactory源码分析(一) ​ 注意:该随笔内容完全引自https://blog.csdn.net/u014634338/article/details/82865644,写的 ...

随机推荐

  1. 【bzoj 3252】攻略

    题意 我们想到一个贪心,就是每次找到根路径前缀和最大的一个点,取走这条路径,同时把这条路径上的点权变成\(0\) 正确性显然 进一步发现我们需要从树上选择\(m\)条链使得链的总和最大 于是我们考虑换 ...

  2. numpy的array数据类型(创建)

    import numpy as np # 创建 # 创建一维数组 a = np.array([1, 2, 3]) print(a) ''' [1 2 3] ''' # 创建多维数组 b = np.ar ...

  3. [源码分析]ArrayList

    add public boolean add(E e) { //先确保数组容量 ensureCapacityInternal(size + 1); //直接将值放在size位置 elementData ...

  4. eclipse中文乱码解决

    1. 改变整个文件类型的编码格式 1)  eclipse->window->preferences->General->Content Types    2)  找到要修改的文 ...

  5. django 模板关闭自动转义

    Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全.但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰 ...

  6. Python中为什么要使用self?

    为什么使用self? class One: def prt(self): print(123) t = One() t.prt() t.prt()和t.prt(t)输出结果是一样的. 当我们调用t.p ...

  7. ddt 数据处理调用excel数据建模

    1.数据模型: 2.数据处理 最终返回数据:[(),()] 格式 ddt调用: import ddtimport unittest @ddt.ddtclass Test(unittest.TestCa ...

  8. XCode iOS之应用程序标题本地化

    1.XCode项目中创建一个.strings 扩展名的文件:打开File > New > File,选择Resource中Strings Fils,如图:点击下一步,为文件命名为(强烈建议 ...

  9. Vue脚手架搭建步骤

    Vue脚手架的搭建步骤 1.   去node.js官网下载node.js并安装,如下图: 2.   找到下载的文件并点击安装: 一直到finish完成.安装成功 3.   通过DOS密令打开: 输入: ...

  10. python基础学习1-计数器实例

    #!/usr/bin/env python # -*- coding:utf-8 -*- import time as t class MyTimer: def __init__(self):#重写初 ...