spring bean 实例化过程解决循环依赖
时间: 2023-10-29 14:29:36 浏览: 123
Spring 的循环依赖问题一般是通过“提前暴露”一个还未完全初始化的 bean 实例来解决。具体步骤如下:
1. 当 Spring 容器创建 bean 实例时,首先会检查该 bean 是否在之前已经创建过了。如果之前已经创建过了,则直接返回之前创建的 bean 实例。
2. 如果该 bean 是一个循环依赖的 bean,那么 Spring 会返回一个尚未完全初始化的 bean 实例,同时将该实例的引用保存在一个“早期引用”缓存中。
3. Spring 会继续创建其他的 bean。
4. 当其他的 bean 创建完毕后,Spring 会回到之前的“早期引用”缓存中,为其中的 bean 实例完成依赖注入和初始化操作。这样,循环依赖的问题就被完美地解决了。
需要注意的是,如果循环依赖的 bean 中存在构造函数的循环依赖,那么上述方法可能无法解决该问题,此时需要考虑其他的解决方案,比如使用 setter 方法注入依赖等。
相关问题
spring bean实例化
### Spring 框架中的 Bean 实例化过程
#### 1. 加载配置元数据
Spring 容器通过读取 XML 文件、注解或 Java 配置类来加载关于应用程序对象(即 beans)的定义信息。这些元数据包含了创建和组装应用程序所需的全部必要信息。
#### 2. 注册 BeanDefinition
容器解析并注册每一个 bean 的定义到内部的数据结构中,通常是一个 `BeanFactory` 或者更高级别的 `ApplicationContext` 中。这一步骤会涉及到对各种自定义作用域的支持处理[^1]。
#### 3. 创建 Bean 实例前准备
当请求某个特定类型的 bean 时,在实际创建该对象之前可能会触发一些前置处理器的工作,比如实现了接口 `InstantiationAwareBeanPostProcessor` 和 `MergedBeanDefinitionPostProcessor` 的组件可以在此阶段介入以修改即将被实例化的 bean 属性或其他特性。
#### 4. 构造函数调用与依赖注入
一旦所有的准备工作完成,则会按照指定的方式——通常是默认无参构造方法或者是带有参数列表的形式去真正构建目标对象;与此同时还会执行设值注入操作给定属性赋初值,并且满足其对外部协作伙伴的需求关系。
```java
// 假设有如下简单的JavaBean
public class MyService {
private AnotherService anotherService;
public void setAnotherService(AnotherService anotherService){
this.anotherService = anotherService;
}
}
```
在这个例子中,如果 `MyService` 是由 Spring 管理的一个 bean ,那么它将会经历上述提到的过程,包括但不限于设置它的 `anotherService` 属性。
#### 5. 初始化前后回调机制
对于那些实现了一些特殊生命周期接口的对象来说,它们可以在完全初始化之后得到通知以便做一些额外的任务。例如:
- 如果一个 bean 实现了 `InitializingBean` 接口的话,那么在其所有属性都被设置了以后就会自动调用 `afterPropertiesSet()` 方法;
- 可以为任意 bean 显式地声明 `<bean init-method="methodName"/>` 来指明希望在初始化完成后运行的方法名称;
- 同样也存在允许其他监听者参与到这个事件链路里的可能性,如 `ApplicationListener<ContextRefreshedEvent>` 类型的服务会在上下文刷新完毕后收到消息提示。
#### 6. 解决单例模式下的循环依赖问题
针对可能出现的单例模式下 A -> B -> C 这样的环形引用情况,Spring 提供了一个三级缓存方案用于管理正在创建但还未最终装配好的 singleton 对象们。具体而言就是先放入 early 单例对象缓存 (singletonObjects),再逐步完善直至移至正常使用的 final 缓存 (finishedBeans)。
#### 7. 销毁资源释放工作
最后需要注意的是,即使是在应用关闭期间也需要妥善清理不再需要的资源。为此目的而设计有相应的销毁钩子函数可供开发者利用,像 `DisposableBean#destroy()`, 自定义 destroy method, 或者是基于事件驱动模型的通知方式等都可以帮助确保优雅退出而不留下任何垃圾残留物。
spring事务传播机制 和 spring bean的生命周期和 循环依赖怎么解决的介绍一下
1. Spring事务传播机制
事务传播机制是指事务方法被嵌套调用时,如何处理事务,Spring提供了七种事务传播行为:
- REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
- SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则不使用事务。
- MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
- REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则挂起当前事务。
- NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则挂起当前事务。
- NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
- NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则创建一个新的事务。
2. Spring Bean的生命周期
Spring容器管理Bean的生命周期,包括如下阶段:
- 实例化:当容器接收到创建Bean的请求时,会使用Java反射机制创建一个Bean对象。
- 属性赋值:将容器中配置的属性值赋值给Bean对象。
- BeanPostProcessor的前置处理:可以在Bean初始化之前进行一些处理,比如数据校验。
- 初始化:当Bean的属性赋值完成后,容器会调用Bean的初始化方法,进行一些初始化操作。
- BeanPostProcessor的后置处理:可以在Bean初始化之后进行一些处理,比如增强Bean功能。
- 使用:容器将Bean对象交给使用者使用。
- 销毁:当容器关闭时,会调用Bean的销毁方法进行清理操作。
3. Spring循环依赖问题解决方案
Spring通过三级缓存解决循环依赖问题:
- singletonObjects:单例Bean对象缓存池,缓存完全初始化完毕的Bean对象。
- earlySingletonObjects:早期Bean对象缓存池,缓存实例化但未完全初始化的Bean对象。
- singletonFactories:单例Bean对象工厂缓存池,缓存用于创建单例Bean对象的工厂。
当容器创建Bean时,会先将Bean实例化,并放入earlySingletonObjects缓存,然后将创建Bean的工厂放入singletonFactories缓存。当容器对Bean进行属性赋值时,会检查earlySingletonObjects缓存中是否有实例化但未完全初始化的Bean对象,如果有,则使用该Bean对象,否则就继续完成Bean的初始化。当Bean初始化完成后,将Bean对象放入singletonObjects缓存中,并从earlySingletonObjects和singletonFactories缓存中移除。这样就保证了循环依赖问题的解决。
阅读全文
相关推荐














