Bean 的创建和管理

简介: Bean 的创建和管理

在 Spring 框架中,Bean 的创建和管理是其核心功能之一。为了优化 Bean 的创建过程并解决循环依赖等问题,Spring 引入了三级缓存机制。让我们深入探讨这一机制的工作原理和实现细节。

 

1. 什么是三级缓存?

 

Spring 的三级缓存主要用于解决单例 Bean 创建时的循环依赖问题。三级缓存分别是:

 

1. **一级缓存(singletonObjects)**:已经完全初始化好的单例 Bean。

2. **二级缓存(earlySingletonObjects)**:提前暴露的单例对象,尚未完全初始化,但已经实例化。

3. **三级缓存(singletonFactories)**:单例工厂,用于创建 Bean 对象的工厂。

 

2. 三级缓存的具体实现

 

三级缓存的实现主要在 `DefaultSingletonBeanRegistry` 类中进行。以下是该类中的相关属性:

 

```java
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    // 一级缓存:存放完全初始化好的单例 Bean
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
 
    // 二级缓存:提早曝光的单例对象,存放原始的 Bean 实例
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
 
    // 三级缓存:存放单例工厂对象,Bean工厂
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
}
```

 

3. 三级缓存的工作流程

 

3.1 Bean 创建前的准备

 

当 Spring 需要创建一个 Bean 时,会先检查三级缓存,看看是否可以复用现有的 Bean 实例。

 

3.2 从缓存中获取 Bean

 

以下是从缓存中获取 Bean 的代码片段:

 

```java
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 从一级缓存中获取
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            // 如果一级缓存中没有,则从二级缓存中获取
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                // 如果二级缓存中也没有,则从三级缓存中获取,并放入二级缓存中
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}
```

 

3.3 将 Bean 放入缓存

 

当 Bean 被创建出来后,会逐步将其放入各级缓存中,最终放入一级缓存中以表示它已经完全初始化好。

 

```java
protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        this.singletonObjects.put(beanName, singletonObject);
        this.earlySingletonObjects.remove(beanName);
        this.singletonFactories.remove(beanName);
    }
}
```

 

3.4 处理循环依赖

 

当一个 Bean 在创建过程中依赖另一个尚未完全初始化的 Bean 时,Spring 可以通过三级缓存机制提前暴露 Bean 的引用,从而解决循环依赖问题。

 

例如,当 Bean A 依赖 Bean B,而 Bean B 又依赖 Bean A 时,创建过程如下:

 

1. 创建 Bean A,发现需要依赖 Bean B。

2. 检查缓存,发现 Bean B 尚未初始化,于是去创建 Bean B。

3. 创建 Bean B,发现依赖 Bean A。

4. 检查缓存,发现 Bean A 正在创建过程中,但还没有完全初始化。

5. 将 Bean A 的引用提前暴露,通过三级缓存机制,使得 Bean B 可以访问 Bean A。

6. Bean B 创建完成并放入缓存。

7. 返回继续创建 Bean A,使用已经创建好的 Bean B 完成 Bean A 的初始化。

8. 将完全初始化好的 Bean A 放入一级缓存。

 

4. 总结

 

Spring 的三级缓存机制是为了解决单例 Bean 创建过程中的循环依赖问题而设计的。通过引入三级缓存,Spring 可以提前暴露 Bean 的引用,使得其他 Bean 可以在创建过程中使用这些引用,从而有效地解决了循环依赖问题。

 

三级缓存机制的精妙之处在于它分阶段缓存 Bean 实例,从而确保在任何时刻都能找到合适的 Bean 引用,这不仅提高了 Bean 创建的效率,也增强了 Spring 容器的灵活性和健壮性。理解三级缓存机制对于深入掌握 Spring 框架的运行原理和优化应用程序的性能具有重要意义。

目录
相关文章
|
12月前
|
XML Java 数据库连接
“Spring管理JavaBean的过程及Bean的生命周期“
“Spring管理JavaBean的过程及Bean的生命周期“
100 0
|
12月前
|
Java Spring
创建名为 'authFilterRegistration' 的bean时,该bean依赖于一个未满足的依赖关系
创建名为 'authFilterRegistration' 的bean时,该bean依赖于一个未满足的依赖关系
60 1
|
4月前
|
XML druid Java
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
45 0
|
5月前
|
XML Java 数据格式
Spring Bean的定义(含创建Bean的三种方式)
Spring Bean的定义(含创建Bean的三种方式)
|
5月前
|
Java 容器 Spring
SpringBoot:Bean生命周期自定义初始化和销毁
SpringBoot:Bean生命周期自定义初始化和销毁
148 1
|
XML Java 数据库
SpringIOC操作Bean管理--最终章
SpringIOC操作Bean管理--最终章
74 0
|
缓存
|
缓存 Java Spring
|
Java Spring 容器
Spring构造通过工厂创建bean
Spring构造通过工厂创建bean
|
存储 Java Spring
Spring之Bean的生命周期源码解析(三 Bean的创建与销毁)
Spring之Bean的生命周期源码解析(三 Bean的创建与销毁)
221 0