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. 8年前,令我窒息的Java socket体验学习

    本来已经放弃编程了,那时我发誓再也不去IT培训班了,如果找不到工作,我就去工地上打工.可心有不甘,老是惦记着,我不想天天面对生产线,做一个丧失思考能力的操作工,可后来呀,还是走上了程序员之路...这么 ...

  2. const修饰的成员是类成员,还是实例成员?

    很抱歉,我以为只有static修饰的成员是类成员,可以通过类名直接访问,然而,const 修饰的成员也属于类成员,直接通过类名访问,不能通过实例变量访问. 做维护久了,深刻的理解,扎实的基础对写出高质 ...

  3. jquery的fadeTo方法的淡入淡出轮播图插件

    由于对基于jquery的简单插件开发有了一定的了解,慢慢的也对基于jquery的插件开发有了兴趣,在上班结束之后就研究各种插件的思路逻辑.最近开发了一款基于jquery的fadeTo方法的轮播图插件, ...

  4. attr全选第三次失效

    一功能checkbox时隐时现,比如第一次打开有勾选,第n次打开可能就不选了. 经过偶层层抽次剥茧(da da jiang you),终于知道了原因:attr()在二次选中勾选框时,失效. 比如,如下 ...

  5. 20165302 2017-2018-2《Java程序设计》课程总结

    20165302 2017-2018-2<Java程序设计>课程总结 每周作业汇总 预备作业1 对师生关系的看法 预备作业2 C语言基础调查 预备作业3 安装虚拟机,初步学习虚拟机及常用命 ...

  6. 手动安装sublime插件babel-sublime

    (一)手动安装babel 在开发reactjs开发使用sublime时,想要代码高亮显示,需要安装babel-sublime插件,在Preferences中的Package Control菜单搜索In ...

  7. 多线程之CountDownLatch、CyclicBarrier和Semaphore

    Java并发编程:CountDownLatch.CyclicBarrier和Semaphore 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch ...

  8. Jmeter之八大可执行元件及执行顺序

    初步接触Jmeter,对比LoadRunner进行熟悉,╮(╯▽╰)╭.毕竟我对LoadRunner还是比Jmeter熟悉. 1.配置元件 用来提供对静态数据配置的支持.例CSV Data Set c ...

  9. 你都用python来做什么?

    首页发现话题   提问     你都用 Python 来做什么? 关注问题写回答     编程语言 Python 编程 Python 入门 Python 开发 你都用 Python 来做什么? 发现很 ...

  10. python-greenlet模块(协程)

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from greenlet import greenlet   def test1():     print(12)    ...