本文主要研究如何从IOC容器已有的BeanDefinition信息,实例化出Bean对象;
这里还会包括三块重点内容:BeanFactory中getBean的主体思路
Spring如何解决循环依赖问题
Spring中Bean的生命周期
一、BeanFactory中getBean的主体思路
在 Spring 框架中,BeanFactory 是最基本的容器接口,用于获取 Spring 管理的 Bean 对象。它的 getBean 方法是用来获取容器中定义的 Bean 的核心方法。
getBean 方法的主体思路
BeanFactory 的 getBean 方法的大致执行流程如下:
1. 检查缓存:
• getBean 方法首先会检查指定的 Bean 是否已经存在于缓存(或称作单例池)中。
• 如果该 Bean 已经实例化并且是单例模式,它会直接返回缓存中的实例,而不会重新创建。
2. 不存在缓存时,创建 Bean:
• 如果没有缓存,Spring 会根据 Bean 的定义(通常是在配置文件中或通过注解)来创建一个新的 Bean 实例。
• 这会触发依赖注入、初始化等步骤,具体过程取决于 Bean 的定义和作用域。
3. 作用域的管理:
• 如果 Bean 定义为单例(默认作用域),它将保存在容器中,之后的每次调用 getBean 都会返回同一个实例。
• 如果 Bean 定义为原型(prototype)作用域,每次调用 getBean 都会创建一个新的实例。
4. 支持多种类型的返回:
• getBean 方法支持通过类型、名称或者同时结合这两者来查找 Bean。可以根据不同的参数传递方式,Spring 会返回对应类型的 Bean。
• 如果 Bean 的定义中有多个候选项,Spring 会根据匹配策略(例如按名称、按类型等)来决定返回哪个 Bean,若无法找到匹配的 Bean,则抛出异常。
5. 依赖注入与后处理:
• 获取到 Bean 实例后,Spring 会处理依赖注入,注入该 Bean 的依赖对象(如果存在的话)。
• 此外,Spring 会对 Bean 进行后处理,例如 AOP 代理、初始化方法的调用等。
6. 异常处理:
• 如果指定的 Bean 不存在,Spring 会抛出 NoSuchBeanDefinitionException 异常。
• 如果多个符合条件的 Bean 存在,Spring 会抛出 NoUniqueBeanDefinitionException 异常。
核心代码分析
Spring 中 getBean 的具体实现主要在 AbstractBeanFactory 或 DefaultListableBeanFactory 类中。以下是 getBean 方法的一个简化版本:
public Object getBean(String name) throws BeansException {
// 1. 检查是否缓存中存在实例
Object bean = getSingleton(name);
// 2. 如果缓存中没有,创建新的 Bean 实例
if (bean == null) {
bean = createBean(name);
}
// 3. 返回实例
return bean;
}
详细步骤
1. getSingleton:
• 这是一个检查缓存的过程。Spring 会维护一个缓存(通常是 singletonObjects)来存储已创建的单例 Bean。如果某个 Bean 的名称对应的实例存在于缓存中,getSingleton 会直接返回该实例。
2. createBean:
• 如果缓存中没有该 Bean,createBean 会负责创建一个新的 Bean 实例。这个过程包括:
• 创建一个新的 Bean 实例(通过反射或构造函数注入)。
• 填充该 Bean 的属性(依赖注入)。
• 调用 Bean 的初始化方法(如果有的话)。
• 注册 Bean 后处理器(例如 AOP)。
3. 作用域处理:
• 对于原型 Bean,Spring 会创建一个新的实例并返回,不会缓存。
• 对于单例 Bean,Spring 会将创建的实例缓存起来,后续请求都会返回缓存中的实例。
4. 异常抛出:
• 如果 getBean 找不到指定的 Bean,它会抛出 NoSuchBeanDefinitionException。
• 如果请求多个符合条件的 Bean,Spring 会抛出 NoUniqueBeanDefinitionException。
总结
Spring 的 getBean 方法的主体思路是先从缓存中查找 Bean 实例,如果不存在则创建并返回该实例。在此过程中,会考虑 Bean 的作用域、依赖注入、初始化等步骤。getBean 是 Spring 容器的核心方法之一,支持灵活的 Bean 查找和管理。
源码的步骤:
- 这里解析bean的真正name,如果bean是工厂类,name前缀会加&,需要去掉
- 无参单例先从缓存中尝试获取
- 如果bean实例还在创建中,则直接抛出异常
- 如果bean definition 存在于父的bean工厂中,委派给父Bean工厂获取
- 标记这个beanName的实例正在创建确保它的依赖也被初始化
二、Spring如何解决循环依赖问题
首先我们需要说明,Spring只是解决了单例模式下属性依赖的循环问题;Spring为了解决单例的循环依赖问题,使用了三级缓存。


具体的源码
分析getSingleton()的整个过程,Spring首先从一级缓存singletonObjects中获取。若是获取不到,而且对象正在建立中,就再从二级缓存earlySingletonObjects中获取。若是仍是获取不到且容许singletonFactories经过getObject()获取,就从三级缓存singletonFactory.getObject()(三级缓存)获取,若是获取到了则从三级缓存移动到了二级缓存。
但其实Spring只能解决Setter方法注入的依赖,对于构造器注入的无法完成,这是因为构造器注入的是属于强制性的,Spring 必须在创建 Bean 时完全满足依赖关系,因此如果发生循环依赖,Spring 会抛出异常。
三、Spring中Bean的生命周期
Spring 只帮我们管理单例模式 Bean 的完整生命周期,对于 prototype 的 bean ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。


本文主要研究如何从IOC容器已有的BeanDefinition信息,实例化出Bean对象;
这里还会包括三块重点内容:BeanFactory中getBean的主体思路
Spring如何解决循环依赖问题
Spring中Bean的生命周期
一、BeanFactory中getBean的主体思路
在 Spring 框架中,BeanFactory 是最基本的容器接口,用于获取 Spring 管理的 Bean 对象。它的 getBean 方法是用来获取容器中定义的 Bean 的核心方法。
getBean 方法的主体思路
BeanFactory 的 getBean 方法的大致执行流程如下:
1. 检查缓存:
• getBean 方法首先会检查指定的 Bean 是否已经存在于缓存(或称作单例池)中。
• 如果该 Bean 已经实例化并且是单例模式,它会直接返回缓存中的实例,而不会重新创建。
2. 不存在缓存时,创建 Bean:
• 如果没有缓存,Spring 会根据 Bean 的定义(通常是在配置文件中或通过注解)来创建一个新的 Bean 实例。
• 这会触发依赖注入、初始化等步骤,具体过程取决于 Bean 的定义和作用域。
3. 作用域的管理:
• 如果 Bean 定义为单例(默认作用域),它将保存在容器中,之后的每次调用 getBean 都会返回同一个实例。
• 如果 Bean 定义为原型(prototype)作用域,每次调用 getBean 都会创建一个新的实例。
4. 支持多种类型的返回:
• getBean 方法支持通过类型、名称或者同时结合这两者来查找 Bean。可以根据不同的参数传递方式,Spring 会返回对应类型的 Bean。
• 如果 Bean 的定义中有多个候选项,Spring 会根据匹配策略(例如按名称、按类型等)来决定返回哪个 Bean,若无法找到匹配的 Bean,则抛出异常。
5. 依赖注入与后处理:
• 获取到 Bean 实例后,Spring 会处理依赖注入,注入该 Bean 的依赖对象(如果存在的话)。
• 此外,Spring 会对 Bean 进行后处理,例如 AOP 代理、初始化方法的调用等。
6. 异常处理:
• 如果指定的 Bean 不存在,Spring 会抛出 NoSuchBeanDefinitionException 异常。
• 如果多个符合条件的 Bean 存在,Spring 会抛出 NoUniqueBeanDefinitionException 异常。
核心代码分析
Spring 中 getBean 的具体实现主要在 AbstractBeanFactory 或 DefaultListableBeanFactory 类中。以下是 getBean 方法的一个简化版本:
public Object getBean(String name) throws BeansException {
// 1. 检查是否缓存中存在实例
Object bean = getSingleton(name);
}
详细步骤
1. getSingleton:
• 这是一个检查缓存的过程。Spring 会维护一个缓存(通常是 singletonObjects)来存储已创建的单例 Bean。如果某个 Bean 的名称对应的实例存在于缓存中,getSingleton 会直接返回该实例。
2. createBean:
• 如果缓存中没有该 Bean,createBean 会负责创建一个新的 Bean 实例。这个过程包括:
• 创建一个新的 Bean 实例(通过反射或构造函数注入)。
• 填充该 Bean 的属性(依赖注入)。
• 调用 Bean 的初始化方法(如果有的话)。
• 注册 Bean 后处理器(例如 AOP)。
3. 作用域处理:
• 对于原型 Bean,Spring 会创建一个新的实例并返回,不会缓存。
• 对于单例 Bean,Spring 会将创建的实例缓存起来,后续请求都会返回缓存中的实例。
4. 异常抛出:
• 如果 getBean 找不到指定的 Bean,它会抛出 NoSuchBeanDefinitionException。
• 如果请求多个符合条件的 Bean,Spring 会抛出 NoUniqueBeanDefinitionException。
总结
Spring 的 getBean 方法的主体思路是先从缓存中查找 Bean 实例,如果不存在则创建并返回该实例。在此过程中,会考虑 Bean 的作用域、依赖注入、初始化等步骤。getBean 是 Spring 容器的核心方法之一,支持灵活的 Bean 查找和管理。
源码的步骤:
二、Spring如何解决循环依赖问题


首先我们需要说明,Spring只是解决了单例模式下属性依赖的循环问题;Spring为了解决单例的循环依赖问题,使用了三级缓存。
具体的源码
分析getSingleton()的整个过程,Spring首先从一级缓存singletonObjects中获取。若是获取不到,而且对象正在建立中,就再从二级缓存earlySingletonObjects中获取。若是仍是获取不到且容许singletonFactories经过getObject()获取,就从三级缓存singletonFactory.getObject()(三级缓存)获取,若是获取到了则从三级缓存移动到了二级缓存。
但其实Spring只能解决Setter方法注入的依赖,对于构造器注入的无法完成,这是因为构造器注入的是属于强制性的,Spring 必须在创建 Bean 时完全满足依赖关系,因此如果发生循环依赖,Spring 会抛出异常。
三、Spring中Bean的生命周期

Spring 只帮我们管理单例模式 Bean 的完整生命周期,对于 prototype 的 bean ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。