Spring 主要源码分析
Bean的生命周期为:BeanFactory初始化 - Bean注册 - 实例化 - 属性注入 - 初始化 - 后处理
Bean的注册
- 扫描:Spring通过配置(XML配置或Java配置)或自动扫描(
@ComponentScan)来发现应用中定义的Bean。对于自动扫描,Spring会在指定的包路径下查找标注了@Component、@Service、@Repository、@Controller等注解的类 - 解析:一旦Bean被发现,Spring将解析Bean的定义信息,包括Bean的作用域(如单例、原型)、生命周期回调(如
@PostConstruct、@PreDestroy注解方法)、依赖注入的需求(通过@Autowired、@Resource等注解标记)等 ——BeanDefinition - 注册:Spring将Bean的定义信息注册到
BeanDefinitionRegistry中。这是一个重要步骤,因为注册后的Bean定义将被用于后续的Bean实例化和依赖注入过程。此时,Bean还没有被实例化。
BeanDefinition
Spring在初始化过程中,先收集所有bean的元数据信息并注册,bean的元数据描述为接口BeanDefinition,该接口定义了你能想到的一切有关bean的属性信息
BeanDefinition衍生出一系列实现类
- AbstractBeanDefinition: 如同其他Spring类,大部分BeanDefinition接口的逻辑都由该抽象类实现
- GenericBeanDefinition: 是一站式、用户可见的bean definition;可见的bean definition意味着可以在该bean definition上定义post-processor来对bean进行操作
- RootBeanDefinition: 当bean definition存在父子关系的时候,RootBeanDefinition用来承载父元数据的角色(也可独立存在),同时它也作为一个可合并的bean definition使用,在Spring初始化阶段,所有的bean definition均会被(向父级)合并为RootBeanDefinition,子bean definition(GenericBeanDefinition/ChildBeanDefinition)中的定义会覆盖其父bean definition(由parentName指定)的定义
- AnnotatedBeanDefinition: 用来定义注解Bean Definition
BeanDefinitionHolder只是简单捆绑了BeanDefinition、bean-name、bean-alias,用于注册BeanDefinition及别名alias ^BeanDefinitionHolder
BeanRegistry
Bean的注册逻辑分为两步,一为BeanDefinition的注册,二为别名的注册
- BeanDefinition注册的定义在BeanDefinitionRegistry#registerBeanDefinition,其实现使用一个Map<String, BeanDefinition> 来保存bean-name和BeanDefinition的关系
- 别名的注册定义在AliasRegistry#registerAlias,其实现同样使用一个Map<String, String> 来保存别名alias-name和bean-name(或另一个别名alias-name)的关系
注意Bean的注册时机,通常应该在应用上下文的刷新过程之前进行(onRefresh())。一旦上下文被刷新,对Bean定义的任何修改可能不会被识别,或者可能会导致不一致的状态
Bean的实例化
BeanFactory
几个核心接口:
- AliasRegistry bean别名注册和管理
- BeanDefinitionRegistry bean元数据注册和管理
- SingletonBeanRegistry 单例bean注册和管理
- BeanFactory bean工厂,提供各种bean的获取及判断方法
通过上述的类依赖图,对于Bean的实例化,核心实现是在DefaultListableBeanFactory
DefaultListableBeanFactory - AbstractBeanFactory
bean的实例化过程发生在getBean调用阶段(对于singleton则发生在首次调用阶段),getBean的实现方法众多,我们追根溯源,找到最通用的方法AbstractBeanFactory#doGetBean
doGetBean
|
|
Bean Name的转换
在使用bean-name获取bean的时候,除了可以使用原始bean-name之外,还可以使用alias别名等,bean-name的转换则是将传入的’bean-name’一层层转为最原始的bean-name
- 函数canonicalName的作用则是利用别名注册aliasMap,将别名alias转为原始bean-name
- 函数transformedBeanName比较特殊,其是将FactoryBean的bean-name前缀 ‘&’ 去除

尝试获取单例
拿到原始的bean-name之后,便可以实例化bean或者直接获取已经实例化的singleton-bean
在获取singleton-bean的时候一般存在三种情况:1. 还未实例化(或者不是单例);2. 已经实例化;3. 正在实例化;
- 对于 “1. 还未实例化” ,返回null即可,后续进行实例化动作
- 对于 “2. 已经实例化”,直接返回实例化的singleton-bean
- 对于 “3. 正在实例化”,会存在循环依赖问题
Spring中对于singleton-bean,有一个sharedInstance的概念,在调用getSingleton函数时,返回的不一定是完全实例化的singleton-bean,有可能是一个中间状态(创建完成,但未进行属性依赖注入及其他后处理逻辑),这种中间状态会通过getSingleton函数提前曝光出来,目的是为了解决循环依赖
因此,Spring通过提供三层缓存来解决循环依赖问题,并且可以通过这种机制实现诸多的PostProcessor增强Bean,例如AOP
- singletonObjects 缓存已经实例化完成的singleton-bean
-
earlySingletonObjects 缓存正在实例化的、提前曝光的singleton-bean,用于处理循环依赖
-
singletonFactories 缓存用于生成earlySingletonObject的 ObjectFactory
ObjectFactory,定义了一个用于创建、生成对象实例的工厂方法
|
|
因此getSingleton的逻辑如下:

NOTE: 在提前暴露实体中,将相应的ObjectFactory放入了singletonFactories
FactoryBean的处理(sharedInstance存在的逻辑)
==sharedInstance不一定是我们所需要的bean实例==
例如,我们在定义Bean的时候可以通过实现FactoryBean接口来定制bean实例化的逻辑(实现FactoryBean),通过注册FactoryBean类型的Bean,实例化后的原始实例类型同样为FactoryBean,但我们需要的是通过FactoryBean#getObject方法得到的实例,这需要针对FactoryBean做一些处理,即AbstractBeanFactory#getObjectForBeanInstance
Get the object for the given bean instance, either the bean instance itself or its created object in case of a FactoryBean. Now we have the bean instance, which may be a normal bean or a FactoryBean. If it’s a FactoryBean, we use it to create a bean instance.
该函数要实现的逻辑比较简单,如果sharedInstance是 FactoryBean,则使用getObject方法创建真正的实例
getObjectForBeanInstance是一个通用函数,并不只针对通过getSingleton得到的sharedInstance,任何通过缓存或者创建得到的 rawInstance,都需要经过getObjectForBeanInstance处理,拿到真正需要的 beanInstance
|
|
getObjectBeanInstance
在这个判断逻辑中,如果入参name以’&‘开头则直接返回,这里兼容了一种情况,如果需要获取/注入FactoryBean而不是getObject生成的实例,则需要在bean-name/alias-name前加入'&'
对于singleton,FactoryBean#getObject的结果会被缓存到factoryBeanObjectCache,对于缓存中不存在或者不是singleton的情况,会通过FactoryBean#getObject生成 ^factorybeangetobject
FactoryBeanRegistrySupport#getObjectFromFactoryBean
|
|
对于Singleton:
- 首先从缓存中尝试获取,如获取失败,调用[doGetObjectFromFactoryBean](#
FactoryBeanRegistrySupport doGetObjectFromFactoryBean“wikilink”),其中内核是调用FactoryBean#getObject()方法 - 对于需要后处理的Bean,首先判断是否处于正在创建状态(
isSingletonCurrentlyInCreation),并且通过this.beforeSingletonCreate()this.afterSingletonCreation()将实际的BeanPostProcessor过程保护 - 对于
BeanPostProcessor,调用this.postProcessObjectFromFactoryBean,其具体实现在[AbstractAutowireCapableBeanFactory#applyBeanPostProcessorAfterInitialization](#AbstractAutowireCapableBeanFactory applyBeanPostProcessorAfterInitialization“wikilink”)
FactoryBeanRegistrySupport#doGetObjectFromFactoryBean
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorAfterInitialization
postProcessAfterInitialization函数可以对现有bean instance做进一步的处理,甚至可以返回新的bean instance,这就为bean的增强提供了一个非常方便的扩展方式
加载Bean实例 (sharedInstance不存在的逻辑)
Bean的加载/创建分为三大部分
- 将BeanDefinition合并为RootBeanDefinition,类似类继承,子BeanDefinition属性会覆盖父BeanDefinition
- 依次加载所依赖的bean,对于有依赖的情况,优先递归加载依赖的bean
- 按照不同的bean类型,根据BeanDefinition的定义进行加载/创建
BeanDefinition合并 (RootBeanDefinition)
在AbstractBeanFactory#getMergedLocalBeanDefinition中执行核心逻辑
加载dependes-On beans
|
|
该过程中涉及两个中间态
- dependentBeanMap 存储哪些bean依赖了我(哪些bean里注入了我) 如果 beanB -> beanA, beanC -> beanA,key为beanA,value为[beanB, beanC]
- dependenciesForBeanMap 存储我依赖了哪些bean(我注入了哪些bean) 如果 beanA -> beanB, beanA -> beanC,key为beanA,value为[beanB, beanC]
加载singleton bean实例
|
|
其中核心为createBean与getObjectForBeanInstance
- createBean 根据BeanDefinition的内容,创建/初始化 bean instance
- #getObjectBeanInstance 主要处理FactoryBean
createBean被包装在lambda(singletonFactory),重写ObjectFactory#getObject(),作为[getSingleton](#DefaultSingletonBeanRegistry getSingleton(String, ObjectFactory) “wikilink”)的参数
DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory)
同样的,会先在缓存中查找该singleton,如果不存在,创建的核心逻辑在于[createBean](#AbstractAutowireCapableBeanFactory createBean “wikilink”)
AbstractAutowireCapableBeanFactory#createBean
- resolveBeanClass 这一步骤用于锁定bean class,在没有显示指定beanClass的情况下,使用className加载beanClass
- 验证method overrides ==在BeanDefinitionReader 中有提到过lookup-method及replace-method,该步骤是为了确认以上两种配置中的method是否存在==
- 执行InstantiationAwareBeanPostProcessor前处理器(postProcessBeforeInstantiation)
如果这个步骤中生成了"代理"bean instance,则会有一个短路操作,
直接返回该bean instance而不再执行doCreate,其中的核心逻辑为调用this.applyBeanPostProcessorsBeforeInstantiation()^fcb215
|
|
- doCreateBean (AbstractAutowireCapableBeanFactory) 真正bean的创建及初始化过程在此处实现
doCreateBean
|
|
可以将该流程细分为如下:
- [创建Bean实体](#创建Bean实体
AbstractAutowireCapableBeanFactory createBeanInstance“wikilink”) - [BeanDefinition后处理](#BeanDefinition后处理 -
AbstractAutowireCapableBeanFactory applyMergedBeanDefinitionPostProcessors“wikilink”) - 提前暴露实体
- [属性注入](#属性注入 -
AbstractAutowireCapableBeanFactory populateBean“wikilink”) - [初始化](#初始化 -
AbstractAutowireCapableBeanFactory initializeBean“wikilink”) - [注册Disposable](#注册Disposable -
AbstractBeanFactory registerDisposableBeanIfNecessary“wikilink”)
创建Bean实体 - AbstractAutowireCapableBeanFactory#createBeanInstance
- instanceSupplier 从上面的流程图可以看出,创建bean实体不一定会使用到构造函数,可以使用Supplier的方式
- factory method
工厂模式
@Configuration + @Bean的实现方式就是factory-bean + factory-method
[对应的参数获取](#
ConstructorResolver resolvePreparedArguments“wikilink”) - 有参构造函数
AbstractAutowireCapableBeanFactory#autowireConstructor -> [ConstructorResolver#autowireConstructor](#
**ConstructorResolver autowireConstructor**“wikilink”) - 无参构造函数 与有参构造创建过程一致,除了不需要参数的依赖注入,使用默认无参构造函数进行实例化
ConstructorResolver#resolvePreparedArguments
使用指定(类)bean的(静态)方法创建bean实体的逻辑在ConstructorResolver#instantiate(String, RootBeanDefinition, Object, Method, args),而真正的逻辑在SimpleInstantiationStrategy#instantiate(RootBeanDefinition, String, BeanFactory, Object, Method, Object…),其核心的执行逻辑非常简单,有了方法factoryMethod(factoryBean)及入参args,便可以调用该方法创建bean实体
|
|
factoryBean可以通过beanFactory.getBean获取到(正是当前在讲的逻辑),factoryMethod可以通过反射获取到,而入参args就从ConstructorResolver#resolvePreparedArguments中获取,即是Spring中依赖注入的核心实现
该函数的作用是将BeanDefinition中定义的入参转换为需要的参数(==将BeanDefinitionReader中封装的对象转换==)
ConstructorResolver#autowireConstructor
同样的,调用ConstructorResolver#resolvePreparedArguments进行参数的解析和转换(参数的依赖注入),然后调用 [ConstructorResolver#instantiate](#ConstructorResolver instantiate “wikilink”) 来创建Bean实例
ConstructorResolver#instantiate
内部并没有统一利用反射技术直接使用构造函数创建,而是通过InstantiationStrategy.instantiate进行创建
- 没有设置override-method时,直接使用构造函数创建
- 设置了override-method时,使用cglib技术构造代理类,并代理override方法
Spring默认的实例化策略为CglibSubclassingInstantiationStrategy
BeanDefinition后处理 - AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
在属性注入之前提供一次机会来对BeanDefinition进行处理,内部执行所有注册MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法
[!hint] MergedBeanDefinitionPostProcessor
MergedBeanDefinitionPostProcessor是一个特定类型的BeanPostProcessor。MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法允许在实例化bean之后但在设置bean属性之前,对bean的定义(BeanDefinition)进行后处理。这个阶段是用于修改或增强bean定义的,例如,可以解析注解并相应地修改BeanDefinition的属性。
对于MergedBeanDefinitionPostProcessor的实现类AutowiredAnnotationBeanPostProcessor,其内部方法AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata 实现了两个注解类的解析 @Value 及 @Autowired ,找到注解修饰的Filed或者Method并缓存,具体逻辑在[属性注入](#属性注入 - AbstractAutowireCapableBeanFactory populateBean “wikilink”) ^autowiredAnnotationBeanPostProcessor1
提前暴露实体
通过将AbstractAutowireCapableBeanFactory#getEarlyBeanReference封装为ObjectFactory,调用DefaultSingletonBeanRegistry#addSingletonFactory,将该ObjectFactory缓存在DefaultSingletonBeanRegistry.singletonFactories中,在getBean逻辑中的getSingleton会执行ObjectFactory将singleton提前暴露
==此处即为何时添加ObjectFactory进入singletonFactories中,解决循环依赖==
此时暴露的singleton-bean仅完成了bean的实例化,属性注入、初始化等逻辑均暂未执行
属性注入 - AbstractAutowireCapableBeanFactory#populateBean
在[创建Bean实体](#创建Bean实体 - AbstractAutowireCapableBeanFactory createBeanInstance “wikilink”)中介绍了factory method方式及有参构造函数方式的参数注入逻辑,除此之外还有一种注入便是属性注入
流程中出现了两次InstantiationAwareBeanPostProcessor,在第一次出现中调用的postProcessorAfterInstantiation也与前面的InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation相同,拥有短路操作:如果该步骤生成了"代理"bean instance,直接返回该bean instance而不再执行后续的doCreate;如果有任意一个InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法返回false,则会跳出属性注入的逻辑,官方对此的解释如下
Give any InstantiationAwareBeanPostProcessors the opportunity to modify the state of the bean before properties are set. This can be used, for example, to support styles of field injection.
autowireByName及autowireByType方法作为"候补"补充BeanDefinition的propertyValues
PropertyValue中记录了需要注入的属性信息及需要注入的属性值,那BeanDefinition的propertyValues都来自哪里?xml中的bean配置、自定义的BeanDefinition等
通过注解修饰的属性(方法)通过InstantiationAwareBeanPostProcessor#postProcessProperties进行注入 -> ==AutowiredAnnotationBeanPostProcessor#postProcessProperties & CommonAnnotationBeanPostProcessor#postProcessProperties==
最后,通过AbstractAutowireCapableBeanFactory#applyPropertyValues 将PropertyValue中记录的需要注入的属性,已经依赖的类型(String、RuntimeBeanReference、等),根据不同的类型解析依赖的bean并设置到对应的属性上(==此过程与DefaultListableBeanFactory#doResolveDependency相似==)
初始化 - AbstractAutowireCapableBeanFactory#initializeBean
以上,完成了bean实例的创建和属性注入,之后还有一些初始化的方法,比如各种Aware的setXxx是如何调用的、@PostConstruct是怎么调用的?
注册Disposable - AbstractBeanFactory#registerDisposableBeanIfNecessary
至此,终于完成了bean实例的创建、属性注入以及之后的初始化,此后便可以开始使用了
在使用Spring的过程中经常还会碰到设置销毁逻辑的情况,如数据库连接池、线程池等等,在Spring销毁bean的时候还需要做一些处理,类似于C++中的析构
在bean的创建逻辑中,最后一个步骤则是注册bean的销毁逻辑(DisposableBean)
销毁逻辑的注册有几个条件
- 非prototype(singleton或者注册的scope)
- 非NullBean
- 指定了destroy-method(如xml中指定或者BeanDefinition中直接设置)或者存在**@PreDestroy** 注解的方法(CommonAnnotationBeanPostProcessor.requiresDestruction)
|
|
满足以上条件的bean会被封装为DisposableBeanAdapter,并注册在DefaultSingletonBeanRegistry.disposableBeans中
加载prototype bean实例
|
|
prototype bean的创建与singleton bean类似,只是不会缓存创建完成的bean
加载其他scope bean实例
scope,即作用域,或者可以理解为生命周期
上文介绍了singleton-bean及prototype-bean的创建过程,严格意义上讲以上两种都是一种特殊的scope-bean,分别对应ConfigurableBeanFactory#SCOPE_SINGLETON及ConfigurableBeanFactory#SCOPE_PROTOTYPE,前者作用域为整个IOC容器,也可理解为单例,后者作用域为所注入的bean,每次注入(每次触发getBean)都会重新生成
Spring中还提供很多其他的scope,如WebApplicationContext#SCOPE_REQUEST或WebApplicationContext#SCOPE_SESSION,前者作用域为一次web request,后者作用域为一个web session周期
自定义scope的bean实例创建过程与singleton bean的创建过程十分相似,需要实现Scope的get方法(org.springframework.beans.factory.config.Scope#get)
|
|
Scope接口除了get方法之外,还有一个remove方法,前者用于定义bean的初始化逻辑,后者用于定义bean的销毁逻辑
|
|
WebApplicationContext#SCOPE_SESSION对应的Scope实现见org.springframework.web.context.request.SessionScope
WebApplicationContext#SCOPE_REQUEST对应的Scope实现见org.springframework.web.context.request.RequestScope
以上两种Scope实现都较为简单,前者将初始化的bean存储在request attribute中,后者将初始化的bean存储在http session中
尝试类型转换
以上,完成了bean的创建、属性的注入、dispose逻辑的注册,但获得的bean类型与实际需要的类型可能依然不相符,在最终交付bean之前(getBean)还需要进行一次类型转换,使用PropertyEditor进行类型转换,将bean转换为真正需要的类型后,便完成了整个getBean的使命
Bean销毁过程
bean的创建过程始于DefaultListableBeanFactory#getBean,销毁过程则终于ConfigurableApplicationContext#close,跟踪下去,具体的逻辑在DefaultSingletonBeanRegistry#destroySingletons
- DefaultSingletonBeanRegistry.disposableBeans 需要注册销毁逻辑的bean会被封装为DisposableBeanAdapter并缓存在此处
- DefaultSingletonBeanRegistry.dependentBeanMap 对于存在依赖注入关系的bean,会将bean的依赖关系缓存在此处(dependentBeanMap: 哪些bean依赖了我; dependenciesForBeanMap: 我依赖了哪些bean)
从上图中可以看出,bean的销毁顺序与创建顺序正好相反,如果有 beanA –dependsOn–> beanB –> beanC ,创建(getBean)时一定是beanC -> beanB -> beanA,销毁时一定是 beanA -> beanB -> beanC,以此避免因为依赖关系造成的一些异常情况
循环依赖
earlySingletonObject是用来解决循环依赖的问题,具体时机是在实例化完后属性注入之前,会提前将当前的bean实体暴露出来,以防止在属性注入过程中所注入的bean又依赖当前的bean造成的类似"死锁"的状态
但是存在以下情况,Spring依旧会陷入循环依赖死锁:
- 显式设置dependsOn的循环依赖
|
|
- 构造函数循环依赖
|
|
- factory-method循环依赖
|
|
- 上述三种依赖混合
只要一个循环依赖中的所有bean,其依赖关系都需要在创建bean实例之前进行解决,此循环依赖则一定无解
要打破无解的循环依赖,在构成循环依赖的一个环中,只需要保证其中至少一个Bean的依赖在该Bean创建且暴露earlySingleton之后处理即可,即在属性注入阶段进行属性依赖的处理
|
|
以"bean创建且暴露earlySingleton"为节点,在此之前处理依赖的有instance supplier parameter、factory method parameter、constructor parameter、等,在此之后处理的依赖有 class property、setter parameter等
ApplicationContext
BeanFactory实现了IoC的基础能力,而ApplicationContext是BeanFactory的子类,除了继承IoC的基础能力外
- 支持国际化 (MessageSource)
- 支持资源访问 (ResourcePatternResolver)
- 事件机制 (ApplicationEventPublisher)
- 默认初始化所有Singleton
- 提供扩展能力
无论何种功能的ApplicationContext,在做完基本的初始化后均会调用AbstractApplicationContext#Refresh
AbstractApplicationContext#Refresh
准备上下文 - AbstractApplicationContext#prepareRefresh
该部分主要实现对上下文的准备工作,其主要涉及到两个接口AbstractApplicationContext#initPropertySources及ConfigurablePropertyResolver#validateRequiredProperties,前者由子类实现,用于初始化PropertySource;后者用于对必要属性进行验证
|
|
重写initPropertySources方法,并添加runtimeEnv为必须的环境变量属性,如此在系统启动的时候便会进行检测,对于不存在任何一个必要环境变量的情况均会抛出异常终止启动
加载BeanFactory - AbstractApplicationContext#obtainFreshBeanFactory
该函数内部实现比较简单,重点在refreshBeanFactory,该函数同样由子类实现
对于AbstractRefreshableApplicationContext,refreshBeanFactory基本步骤为
- 创建BeanFactory (DefaultListableBeanFactory)
- 设置BeanFactory
- 加载BeanDefinition
在第3步中,AbstractXmlApplicationContext的实现则是对xml配置文件的解析及加载;AnnotationConfigWebApplicationContext的实现则是对class文件的扫描并加载,以及其他基于AbstractRefreshableApplicationContext的ApplicationContext实现
对于GenericApplicationContext,BeanFactory的创建及BeanDefinition的加载在refresh调用之前早已完成,refreshBeanFactory的实现则是对BeanFactory加载状态的简单校验
AbstractRefreshableApplicationContext & GenericApplicationContext
AbstractRefreshableApplicationContext
对于继承自 AbstractRefreshableApplicationContext 的上下文,例如 ClassPathXmlApplicationContext 或 AnnotationConfigApplicationContext,它们通过覆盖 refreshBeanFactory() 方法来实现具体的 BeanDefinition 加载逻辑。这些上下文类型专门用于从外部资源(如 XML 文件、Java 配置类等)加载配置信息,并将这些配置信息解析为一组 BeanDefinition,然后注册到内部的 BeanFactory 中。这个过程通常发生在上下文的 refresh() 方法调用过程中(我们正在讨论的),这个方法不仅负责加载和注册 BeanDefinition,还包括初始化单例bean、处理别名定义、注册BeanPostProcessor等一系列容器启动时的活动。
[!QUOTE] refresh()关键步骤 ^configurerRelated
- 创建 BeanFactory:
AbstractRefreshableApplicationContext首先会创建一个新的BeanFactory实例,这通常是一个DefaultListableBeanFactory实例。这个BeanFactory实现了BeanDefinitionRegistry接口,使得它能够注册 BeanDefinition。- ==加载 BeanDefinition:接着,上下文会调用特定的方法(例如,对于基于 XML 的配置,会使用
XmlBeanDefinitionReader;对于基于注解的配置,会使用AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner)来加载 BeanDefinition。这些 Reader 和 Scanner 实现了BeanDefinitionRegistry接口的registerBeanDefinition方法来实际完成注册工作。==- 刷新 BeanFactory:加载完所有 BeanDefinition 后,
AbstractRefreshableApplicationContext会对BeanFactory进行刷新,这涉及到预实例化单例、注册BeanPostProcessor、初始化剩余的非懒加载单例等一系列操作。- 发布事件:在整个容器刷新过程中,还会发布各种应用事件,如
ContextRefreshedEvent,允许应用中的其他组件对这些事件作出响应。通过上述步骤,
AbstractRefreshableApplicationContext完成了 BeanDefinition 的加载、注册以及整个 Spring 容器的初始化和刷新工作。在这个过程中,BeanDefinitionRegistry接口扮演了 BeanDefinition 注册的关键角色GenericApplicationContext
GenericApplicationContext 直接实现了 BeanDefinitionRegistry 接口,使得它可以在运行时动态注册 BeanDefinition。与 AbstractRefreshableApplicationContext 的子类不同,GenericApplicationContext 并不专门依赖于外部资源来加载 BeanDefinition。相反,它提供了一套程序化的接口,允许开发者直接在代码中通过调用 registerBeanDefinition(String beanName, BeanDefinition beanDefinition) 方法来注册 BeanDefinition。这种方式使得 GenericApplicationContext 非常灵活,适用于那些需要在运行时动态调整 Spring 配置的场景。
关系和区别
- 加载方式的区别:
AbstractRefreshableApplicationContext的子类通常通过解析配置资源(XML、注解等)来加载 BeanDefinition,而GenericApplicationContext允许以编程方式直接注册 BeanDefinition。 - 使用场景的区别:
AbstractRefreshableApplicationContext的子类适合于静态配置资源的场景,其中配置信息在应用启动时已经确定。GenericApplicationContext更适合于动态配置的场景,比如基于条件的 BeanDefinition 注册或运行时的配置调整。 - 刷新容器的能力:虽然两者都可以通过
refresh()方法来刷新应用上下文,但AbstractRefreshableApplicationContext的子类通常在设计时就考虑了完整的容器刷新流程(包括重新加载配置资源),而GenericApplicationContext刷新主要是为了应用新注册的 BeanDefinition。==前者会重置BeanFactory而后者不会==
填充部分扩展 - AbstractApplicationContext#prepareBeanFactory
该函数执行以下逻辑
- 设置BeanFactory的ClassLoader
- 注册默认BeanExpressionResolver,用于依赖注入时SpEL的支持
- 注册默认PropertyEditor,用于依赖注入时对参数的解析转换
- 注册几个特殊Aware的处理逻辑
- 注册AspectJ相关的几个处理器,用于AOP的支持
- 注册几个特殊的BeanDefinition
==2-3 的核心逻辑在于解析依赖的值,DefaultListableBenFactory#doResolveDependency==
注册几个特殊Aware的处理逻辑
在Bean实例化、注入依赖之后会对Bean进行[最后的初始化](#初始化 - AbstractAutowireCapableBeanFactory initializeBean “wikilink”),调用相应的setter方法分别针对BeanNameAware、BeanClassLoaderAware、BeanFactoryAware进行处理
在该函数中,会注册几个特殊的BeanPostProcessor
|
|
其实现了postProcessBeforeInitialization方法,内部调用ApplicationContextAwareProcessor#invokeAwareInterfaces针对另外的几类Aware进行了处理
除此之外,Spring会将上述几类Aware设置为ignoreDependencyInterface,这意味着以上几类Bean的注入只能通过Aware的方式而不能通过其他属性依赖注入的方式(属性注入、函数参数注入等)
注册特殊的Bean
在使用Spring时,是否有过直接注入BeanFactory亦或是ResourceLoader,这些bean正是在这里被Spring注册进去的,除以上外Spring还注入了
- BeanFactory
- ResourceLoader
- ApplicationEventPublisher
- ApplicationContext
- Environment
- systemProperties - Environment#.getSystemProperties:Map<String, Object>
- systemEnvironment - Environment#.getSystemEnvironment:Map<String, Object>
AbstractApplicationContext#refresh#postProcessBeanFactory()
对于不同的实现类,注册相应的BeanPostProcessor,例如ServletWebServerApplicationContext
激活BeanFactoryPostProcessor - AbstractApplicationContext#invokeBeanFactoryPostProcessors
其内部实现在PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
BeanFactoryPostProcessor的定义非常简单,其postProcessBeanFactory方法允许在bean实例化前对BeanFactory做一些额外的设置
|
|
核心逻辑如下
其中涉及两种类型,BeanDefinitionRegistryPostProcessor及BeanFactoryPostProcessor,前者为后者的子类,BeanDefinitionRegistryPostProcessors提供了额外的接口postProcessBeanDefinitionRegistry,用于更加方便地动态地注册额外的BeanDefinition (registryProcessor.postProcessBeanDefinitionRegistry(registry)),如读取配置文件(json、properties、yml)并解析(或者任何其他的形式),并通过该接口注册相应的BeanDefinition,基于Spring Boot Starter的很多框架均使用该方式进行bean的注册
以上流程图可以看出,优先执行BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry,再执行BeanFactoryPostProcessor#postProcessBeanFactory,各自内部优先执行PriorityOrdered实现,再执行Ordered实现,最后执行无任何排序的实现
注册BeanPostProcessor - AbstractApplicationContext#registerBeanPostProcessors
其内部实现在PostProcessorRegistrationDelegate#registerBeanPostProcessors b
BeanPostProcessor
|
|
- postProcessBeforeInitialization方法在调用bean的init-method之前执行
- postProcessAfterInitialization方法在调用bean的init-method之后执行
- 任何一个方法可对现有bean实例做进一步的修改
- 任何一个方法可返回新的bean实例,用来替代现有的bean实例
第四点即是AOP生成当前Bean代理的方法
InstantiationAwareBeanPostProcessor
该接口继承自BeanPostProcessor,其同样有两个方法,一个在创建bean实例之前调用([createBean](#AbstractAutowireCapableBeanFactory createBean “wikilink”)),一个在创建bean实例之后、属性注入之前调用([属性注入](#属性注入 - AbstractAutowireCapableBeanFactory populateBean “wikilink”))
|
|
AbstractApplicationContext#registerBeanPostProcessors,其内部逻辑与BeanFactoryPostProcessor的注册逻辑类似:
- 找到所有BeanPostProcessor并实例化
- 按照实现的Ordered接口分别放入priorityOrderedPostProcessors、orderedPostProcessors、nonOrderedPostProcessors并各自排序
- 如果实现了MergedBeanDefinitionPostProcessor则放入internalPostProcessors并排序
- 按顺序依次注册priorityOrderedPostProcessors、orderedPostProcessors、nonOrderedPostProcessors
- 最后注册internalPostProcessors
MergedBeanDefinitionPostProcessor其有一个接口postProcessMergedBeanDefinition,在bean实例化完成后属性注入之前被调用,可以用来对当前的BeanDefinition做进一步的修改,如增加PropertyValue等,实现特殊的属性依赖注入,参考[BeanDefinition后处理](#BeanDefinition后处理 - AbstractAutowireCapableBeanFactory applyMergedBeanDefinitionPostProcessors “wikilink”)与[属性注入](#属性注入 - AbstractAutowireCapableBeanFactory populateBean “wikilink”)
初始化MessageSource - AbstractApplicationContext#initMessageSource
Spring的MessageSource提供了国际化能力,在开发者未注册MessageSource的情况下Spring会提供一个默认的DelegatingMessageSource
初始化ApplicationEventMulticaster - AbstractApplicationContext#initApplicationEventMulticaster
Spring提供了一套事件(ApplicationEvent)的发布&订阅机制,开发者可自定义事件(继承ApplicationEvent),注册事件监听器来订阅消费事件(实现ApplicationListener 或使用@EventListener 注解),并使用ApplicationEventPublisher(直接依赖注入或者使用ApplicationEventPublisherAware)发送事件,使用示例可参考https://www.baeldung.com/spri…
其实ApplicationContext实现了ApplicationEventPublisher,跟踪其publishEvent方法会发现,最终调用了AbstractApplicationContext#applicationEventMulticaster.multicastEvent,开发者可以自行注册一个ApplicationEventMulticaster,如果没有Spring会提供一个默认的SimpleApplicationEventMulticaster
SimpleApplicationEventMulticaster#multicastEvent的逻辑比较简单,会根据事件的类型找到可以处理的所有ApplicationListener,依次调用它们的onApplicationEvent方法消费事件
|
|
默认情况下会同步、顺序的调用listeners的onApplicationEvent方法,只有设置了executor才会异步调用,不过这样的控制粒度比较粗,要么全部同步消费要么全部异步消费,比较细粒度的控制事件的消费有几种常用方法
- 使用@Async注解,独立控制某一listener异步消费(https://www.baeldung.com/spri…)
- 自行编码,将onApplicationEvent逻辑放在线程中执行
- 注册自定义的ApplicationEventMulticaster,内部实现自己的同步、异步Event处理逻辑
注册ApplicationListener - AbstractApplicationContext#registerListeners
这里的逻辑比较简单
- 在BeanFactory中找到ApplicationListener类型的bean并实例化
- 调用ApplicationEventMulticaster#addApplicationListenerBean方法将ApplicationListeners注册进去
初始化所有非Lazy Bean - AbstractApplicationContext#finishBeanFactoryInitialization
对于Singleton Bean而言,实例化发生在首次getBean,但你是否有疑惑,我们只是注册了众多Singleton Bean,但在Spring初始化完成后所有的Singleton Bean(Lazy Bean除外)均已经完成实例化
回到AbstractApplicationContext#finishBeanFactoryInitialization,该函数会实现几个逻辑
- 如果自定义了ConversionService(另一种注入类型转换的方式)类型bean且bean-name为conversionService,则将其注册到BeanFactory中
- 如果BeanFactory中不存在EmbeddedValueResolver(PropertyResourceConfigurer会注册一个PlaceholderResolvingStringValueResolver到BeanFactory中),则会注册一个默认的StringValueResolver用来处理
${ ... }类型的值(Environment#resolvePlaceholders) - 找到所有非Lazy的Singleton BeanDefinition进行实例化(getBean)
- 如果是FactoryBean,则在bean name前加上’&’,并实例化该FactoryBean,随后实例化真实的bean
- 如果不是FactoryBean,则直接实例化该bean
- 执行SmartInitializingSingleton实现类的afterSingletonsInstantiated方法
Refresh的后续动作 - AbstractApplicationContext#finishRefresh
除了一些中间状态需要清理外,还有两件比较特殊的地方
LifecycleProcessor - AbstractApplicationContext#initLifecycleProcessor
Spring提供了LifecycleProcessor用于监听BeanFactory的refresh及close,在BeanFactory的各阶段会调用LifecycleProcessor的onFresh及onClose方法
开发者可以自行注册LifecycleProcessor类型的bean,bean-name必须为"lifecycleProcessor",否则Spring会提供一个默认的DefaultLifecycleProcessor
之后则会触发LifecycleProcessor的onFresh方法
除此之外,还可以监听ContextRefreshedEvent及ContextClosedEvent消息
refresh事件
在BeanFactory初始化完成后,则会发出ContextRefreshedEvent事件
BeanFactory的销毁 - AbstractApplicationContext#registerShutdownHook
该函数用来注册BeanFactory的销毁逻辑
|
|
其直接使用了java的addShutdownHook函数,在jvm进程正常退出的时候触发
AbstractApplicationContext#doClose函数定义了BeanFactory具体的销毁过程
- 发出ContextClosedEvent事件
- 触发LifecycleProcessor的onClose方法
- 销毁bean,细节参考Bean销毁过程
- 由子类实现的AbstractApplicationContext#closeBeanFactory及AbstractApplicationContext#onClose方法
ASIDE
- BeanDefinition的加载在[AbstractApplicationContext#obtainFreshBeanFactory](#加载BeanFactory -
AbstractApplicationContext obtainFreshBeanFactory“wikilink”)中实现 - TODO
#{ ... }类型值的解析由StandardBeanExpressionResolve实现${ ... }类型值的解析由PlaceholderResolvingStringValueResolver实现- Spring提供了众多默认的PropertyEditor,若需要自定义PropertyEditor可以通过注册CustomEditorConfigurer实现
- Spring提供了众多Aware,若需要自定义Aware可以通过BeanPostProcessor实现
- BeanFactoryPostProcessor用于在实例化bean之前对BeanFactory做额外的动作 如,PropertyResourceConfigurer用来将PlaceholderResolvingStringValueResolver注册到BeanFactory的embeddedValueResolvers中
- [BeanDefinitionRegistryPostProcessor](#激活BeanFactoryPostProcessor -
AbstractApplicationContext invokeBeanFactoryPostProcessors“wikilink”)用于在实例化bean之前(动态)注册额外的BeanDefinition ^fa1ce8 - BeanPostProcessor用于在调用bean的init-method前后,对实例化完成的bean做一些额外的干预 如,CommonAnnotationBeanPostProcessor用来处理@PostConstructor,AbstractAdvisingBeanPostProcessor用来实现AOP
ApplicationContext具体实现类 - AnnotationConfigApplicationContext
|
|
无参构造
|
|
AnnotatedBeanDefinitionReader
|
|
这里会将ConfigurationClassPostProcessor后置处理器加入到BeanFactory中,它继承自BeanFactoryPostProcessor,也就是说一会会在BeanFactory初始化完成之后进行后置处理,同时这里也会注册一个AutowiredAnnotationBeanPostProcessor后置处理器到BeanFactory,它继承自BeanPostProcessor,用于处理后续生成的Bean对象,其实看名字就知道,这玩意就是为了处理@Autowire、@Value这种注解,用于自动注入
注册传入的配置类 - register
|
|
[Refresh](#AbstractApplicationContext Refresh “wikilink”)
==TODO==
- ☒ Spring AOP
- ☐ 注解运行逻辑
@Component与@Bean的区别- JavaSSM#^473168
- ☐ @Bean 在处理属性注入时?
- ☒ AnnotationConfigApplicationContext - 与 配置类的关系 - 具体例子
- ☐ BeanDefinitionReader和BeanDefinitionRegistry
- ☐ 完善调用链图
配置类的注册 -
ConfigurationClassPostProcessor
ConfigurationClassPostProcessor继承自BeanDefinitionRegistryPostProcessor -> BeanFactoryPostProcessor,这个后置处理器是Spring中提供的,这是专门用于处理配置类的后置处理器,其中ImportBeanDefinitionRegistrar,还有ImportSelector都是靠它来处理
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
内部调用 processConfigBeanDefinitions(BeanDefinitionRegistry) 方法
|
|
ConfigurationClassParser#parse(candidates)
|
|
内部遍历candidates中的每一个BeanDefinitionHolder,调用parse的多态方法,最终调用ConfigurationClassParser#processConfigurationClass,最后调用deferredImportSelectorHandler.process()处理DeferredImportSelector相关的Bean注册 ^processConfigurationClass
首先判断条件注释,即处理@Conditional相关注解
然后将不同来源的配置类源信息通过asSourceClass进行封装,交给最核心的调用[doProcessConfigurationClass](#ConfigurationClassParser doProcessConfigurationClass “wikilink”)
将配置类
ConfigurationClass实例化为SourceClass。这样做的目的是为了让后续的处理逻辑能够通过SourceClass访问到配置类中定义的所有相关信息(比如注解信息,Meta-info),并进行相应的处理。例如,通过SourceClass可以读取配置类上的@ComponentScan注解,并执行组件扫描;读取@Import注解,并处理导入的配置类或组件;读取@Bean方法,并注册对应的Bean定义等。
ConfigurationClassParser#doProcessConfigurationClass
|
|
该函数依次解决如下问题:
- 处理@Component注解
- 处理@PropertySource和@PropertySources注解
- 处理@ComponentScan和@ComponentScans
- 处理@Import注解
- 处理@ImportResource注解
- 处理@Bean注解的方法
- 处理接口上的默认方法和超类
其中的核心是处理@Import注解,通过调用 [ConfigurationClassParser#processImports](#ConfigurationClassParser processImports “wikilink”)
ConfigurationClassParser#processImports
注意其第三个入参Collection<SourceClass> importCandidates,它是通过调用getImports(sourceClass)方法,从给定的sourceClass中提取所有@Import注解指定的类,如果sourceClass是普通的配置类,直接通过isEmpty()返回
|
|
代码遍历每一个@Import注解指定的候选类,根据不同类型进行处理
ImportSelector实现ImportSelectorDeferredImportSelectorImportBeanDefinitionRegistar实现- 普通的配置类
针对ImportSelector
通过selector.selectImports()与asSourceClasses()方法将需要导入的类重新封装为SourceClass,递归调用processImports
针对DeferredImportSelector
通过调用ConfigurationClassParser的内部类DeferredImportSelectorHandler#handle()方法,将其封装为DeferredImportSelectorHolder ,加入待处理的List - deferredImportSelectors
在ConfigurationClassParser#parse[处理完所有候选配置类后](#ConfigurationClassParser parse(candidates) “wikilink”),调用DeferredImportSelectorHandler#process()方法,该方法将加入deferredImportSelectors中的所有DeferredImportSelectorHolder执行内部类的DeferredImportSelectorGroupingHandler#register方法,得到包装好的、已经分组完毕的DeferredImportSelectorGrouping,然后调用DeferredImportSelectorGroupingHandler#processGroupImports(),处理组内所有的延迟导入 (DeferredImportSelector)
DeferredImportSelectorGroupingHandler#register
|
|
- 首先尝试获取
DeferredImportSelector指定的导入组 (ImportGroup),如果没有指定特定的导入组,则使用DeferredImportSelector本身作为组的Key - 尝试从一个名为
groupings的映射中获取或创建一个与导入组对应的DeferredImportSelectorGrouping对象。如果映射中尚未存在与当前组对应的分组,那么将创建一个新的分组,并将其加入到映射中- 注意,此处的Group逻辑是将
DeferredImportSelector.Group这个内部接口包装到ConfigurationClassParser.DeferredImportSelectorGourping这个内部类中,其内部维护了一个DeferredImportSelector.Group对象和List<DeferredImportSelectorHolder>对象
- 注意,此处的Group逻辑是将
- 调用
DeferredImportSelectGrouping#add(DeferredImportSelectorHolder),将DeferredImportSelectorHolder加入内部类维护的Grouping中 (静态类) - 最后,代码将当前
DeferredImportSelectorHolder对应的配置类(ConfigurationClass)及其元数据添加到一个名为configurationClasses的映射中。这确保了后续能够快速访问到与特定DeferredImportSelector相关联的配置类
DeferredImportSelectorGroupingHandler#processGroupImports
|
|
- 遍历保存在
Groups - DeferredImportSelectorGroupingHandler中的DeferredImportSelectorGroup对象,调用DeferredImportSelectorGroup#getImports()方法 DeferredImportSelectorGroup#getImports()方法调用DeferredImportSelectorGroup中维护的真实的Group -DeferredImportSelector.Group#process方法,然后返回含有meta-info的Entry- 使用内部维护的
Map(在register中put),根据Entry.meta-info得到对应的ConfigurationClass,调用ConfigurationClassParser#processImports,和[前面](#ConfigurationClassParser processImports“wikilink”)一样递归调用进行处理
所以根据以上分析,DeferredImportSelector最终的处理逻辑在于DeferredImportSelector.Group#process() ^db8805
针对ImportBeanDefinitionRegistar
|
|
调用ConfigurationClass#addImportBeanDefinitionRegistrar方法,将对应的实例加入configClass对应的Collection类中,后续在[loadBeanDefinitions](#ConfigurationClassBeanDefinitionReader loadBeanDefinitions “wikilink”)中调用其registerBeanDefinitions,注册相应的BeanDefinition
针对普通配置类
不使用特殊机制,直接递归调用processConfigurationClass
ConfigurationClassParser#getConfigurationClasses
返回从前面得到的所有待配置的配置类
ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
^98f726
|
|
通过遍历每一个配置类,调用loadBeanDefinitionsForConfigurationClass方法 ^f6a27a
- registerBeanDefinitionForImportedConfigurationClass(configClass) 注册配置类自身
- loadBeanDefinitionsForBeanMethod(beanMethod) 注册@Bean注解标识的方法
- loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); 注册@ImportResource引入的XML配置文件中读取的bean定义
- loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); 注册configClass中经过解析后保存的所有ImportBeanDefinitionRegistrar,注册对应的BeanDefinition
AOP
AOP的实现类是AnnotationAwareAspectJAutoProxyCreator,其是BeanPostProcessor的实现类,具体来说,是InstantiationAwareBeanPostProcessor的实现类,在实例化Bean过程中,通过调用BeanPostProcessor中的实例化前处理器进行短路,得到相应的代理Bean
@EnableAspectJAutoProxy
|
|
这个注解使用@Import导入了AspectJAutoProxyRegistrar,其是ImportBeanDefinitionRegistrar的实现类,会在处理配置类相应@Import机制的时候将AnnotationAwareAspectJAutoProxyCreator实现类注册到容器中,即注册到BeanDefinition中,实现相应的实例化前处理器功能 (InstantiationAwareBeanPostProcessor)