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. 1054. [HAOI2008]移动玩具【BFS】

    Description 在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动 时只能将玩具向上下左右四个方向移动,并且移动的位置不能有玩具,请你用最少的移 ...

  2. yii在哪些情况下可以加载yiilite.php?

    yii权威指南上说,在开启apc缓存的情况下,可以加载yiilite.php提升性能.我有以下几点疑问: 1.开启apc缓存的情况下,引入yiilite.php能提升性能的原因是因为缓存了opcode ...

  3. openstack排除查找错误的两种方法

    1.openstack日志一般放在什么什么位置?2.如何调试openstack命令执行过程? 我们会经常错误,但是我们碰到错误该怎么做,该如何找到原因.对于openstack有两种办法:在上一篇文章h ...

  4. ES6新特性1:let和const

    本文摘自ECMAScript6入门,转载请注明出处. 一.let 1. ES6增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. { let a ...

  5. python基础整理7——爬虫——爬虫开发工具

    HTTP代理神器Fiddler Fiddler是一款强大Web调试工具,它能记录所有客户端和服务器的HTTP请求. Fiddler启动的时候,默认IE的代理设为了127.0.0.1:8888,而其他浏 ...

  6. 列表中不限制宽度,hover时,字体font-weight:bold,防止抖动

    项目一个小问题困扰了很久,在一个没有限制宽度的列表容器中,如果给hover时,给字体➕'font-wieght:bold'容器就会变宽,然后移动的下一个容器,就会出现抖动,这样很是影响用户体验,于是在 ...

  7. $Mayan$游戏

    \(Mayan\)游戏 好啊,一年(半年)来的梦魇,终于结束了. 其实我从来没料到整体竟然会如此暴力--做的时候机房里冷得很,感觉晕晕乎乎地做完了,晕晕乎乎地调了好久,晕晕乎乎地听(看了题解的)\(q ...

  8. 流程一直处于Running状态,应该怎么停止?

    流程一直处于Running状态,应该怎么停止? 概述 我们有遇到这种情况:可能由于某些原因,流程发起后一直处于Running状态,然后我们想Stop掉这些出问题的流程,这个时候你在Workspace里 ...

  9. GoogleTest初探(1)

    此篇主要了解一下GoogleTest中的断言. 总的来说,GoogleTest中的断言分为两大类:EXPECT_*和ASSERT_*,这两者在测试成功或失败后均会给出测试报告,区别是前者在测试失败后会 ...

  10. 【数据结构与算法】001—栈与队列(Python)

    栈与队列 1.栈(stacks)是一种只能通过访问其一端来实现数据存储与检索的线性数据结构,具有后进先出(last in first out,LIFO)的特征 2.队列(queue)是一种具有先进先出 ...