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. async/await actor promise 异步编程

    Python协程:从yield/send到async/await http://blog.guoyb.com/2016/07/03/python-coroutine/ Async/Await替代Pro ...

  2. Loj #2256. 「SNOI2017」英雄联盟

    题目 我就是个丝薄 如果要用\(dp_i\)表示凑出\(i\)的最小花费显然不可能的 之后大力猜想能凑出来的状态不会很多,我的暴力也告诉我不是很多,好像也确实不多的样子,大概\(4e4\)左右 但是我 ...

  3. js之点击值发生变化

    点击值发生变化,应用场景,比如像阿里云那样我通常密码是以******的形式存在,我必须要点击查看,它才会以明文显示. 在实际开发中,比如以智能门锁为例,安装门锁时,有个叫密码输入框的表单,这个是选填项 ...

  4. iis7中session丢失的解决方法小结

    这篇文章主要介绍了在windows server 2008系统中,session丢失的解决方法,供大家学习参考 问题描述: Windows Server 2008 +IIS +ASP.net +SQL ...

  5. ps命令使用详解

    转自:http://blog.csdn.net/lsbhjshyn/article/details/18549869 ps:要对进程进行监测和控制,首先必须要了解当前进程的情况,也就是需要查看当前进程 ...

  6. RabbitMQ如何保证发送端消息的可靠投递

    消息发布者向RabbitMQ进行消息投递时默认情况下是不返回发布者该条消息在broker中的状态的,也就是说发布者不知道这条消息是否真的抵达RabbitMQ的broker之上,也因此会发生消息丢失的情 ...

  7. jquery 中的dom操作

    jquery DOM 分为元素操作.属性操作.样式操作. 一.元素操作 1.查找 ①工具:jQuery选择器 2.创建和添加 ①代码格式:变量 = $('要创建的元素'): 注意点: 1 要使用标准的 ...

  8. Golint的简易使用方法

    根据作者的说法: Golint is a linter for Go source code. Golint differs from gofmt. Gofmt reformats Go source ...

  9. 一些漂亮的js库

    http://tympanus.net/Development/ModalWindowEffects/ http://js1k.com/2013-spring/demos http://dimseme ...

  10. Java基础——常用类之日期时间类

    如果有机会,请尝试Java8中全新的时间日期API!(参见Java8新特性随笔) 如果还是使用Java7及之前的版本,那么你可以尝试一些工具类(参考使用工具类相关的Hutool-DateUtil) 如 ...