Spring单例初始化流程

本文详细介绍了Spring中单例bean的初始化过程,包括createBeanInstance、populateBean和initializeBean三个步骤,以及BeanPostProcessor和@PostConstruct等初始化方法的调用顺序。同时,解释了Spring为解决循环依赖问题而采用的三级缓存机制:singletonObjects(一级缓存)、singletonFactories(三级缓存)和earlySingletonObjects(二级缓存)。在获取bean时,会按顺序从这三级缓存中查找。最后,讨论了isSingletonCurrentlyInCreation和allowEarlyReference参数的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

Spring的单例对象的初始化主要分为三步。
在这里插入图片描述

  1. createBeanInstance:实例化,其实就是 调用对象的构造方法实例化对象。
  2. populateBean:填充属性,这一步主要是多bean的依赖属性进行填充。
  3. initializeBean:调用spring xml中的init() 方法,或者@PostConstruct注解的init()方法。

初始化Bean的先后顺序

1、bean实例化;
2、populateBean填充属性;
3、BeanPostProcessor的postProcessBeforeInitialization方法;
4、注解了@PostConstruct的方法;
5、InitializingBean的afterPropertiesSet方法;
6、bean的指定初始化方法:init-method;
6、BeanPostProcessor的postProcessAfterInitialization方法;

三级缓存

对于单例来说,在Spring容器整个生命周期内,有且只有一个对象,所以很容易想到这个对象应该存在Cache中,Spring为了解决单例的循环依赖问题,使用了三级缓存。

哪三级缓存

/** Cache of singleton objects: bean name --> bean instance */
// 一级缓存,完全初始化好的单例放入其中,从上下文获取的单例就是从这里获取
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
/** Cache of singleton factories: bean name --> ObjectFactory */
// 三级缓存,存放实例化的对象,还没有对其进行属性填充
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
/** Cache of early singleton objects: bean name --> bean instance */
// 二级缓存,提前暴光的单例对象的Cache(用于检测循环引用,与singletonFactories互斥,就是要么在singletonFactories中要么在earlySingletonObjects中),
// 也只是实例化,但还没有填充属性
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

从缓存中获取bean

在获取bean的时候,首先是根据beanName从缓存中获取bean,如果获取不到就通过单列工厂创建,具体的流程可以看单列初始化流程图。
缓存中获取bean的逻辑是先从singletonObjects(一级缓存)获取,如果获取不到去earlySingletonObjects(二级缓存)获取,还是获取不到就从singletonFactories(三级缓存)获取。
源码如下:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            Map var4 = this.singletonObjects;
            synchronized(this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject != NULL_OBJECT ? singletonObject : null;
    }

注释

  1. isSingletonCurrentlyInCreation()判断当前单例bean是否正在创建中,
    也就是没有初始化完成(比如A的构造器依赖了B对象所以得先去创建B对象,
    或则在A的populateBean过程中依赖了B对象,得先去创建B对象,这时的A就是处于创建中的状态。)
  2. allowEarlyReference 是否允许从singletonFactories中通过getObject拿到对象。

单例初始流程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

### Spring 框架启动与初始化详细流程 Spring 容器的初始化过程是一个复杂的过程,涉及多个阶段和组件协作。以下是详细的解析: #### 1. 资源加载 Spring 启动时会先通过 `DefaultResourceLoader` 加载配置文件或其他形式的应用程序 Bean 配置信息[^5]。这些配置可以是 XML 文件、Java 注解或者 Groovy DSL 等多种形式。 #### 2. 创建 BeanDefinition 注册表 在完成资源配置加载之后,Spring 将基于所读取的信息构建一张 **BeanDefinition 注册表**。此注册表记录了所有的 Bean 及其元数据(如作用域、生命周期回调方法等),并将其存储于内存中以便后续操作[^3]。 #### 3. 初始化 DefaultListableBeanFactory 接着,在容器初始化的过程中,会调用一系列钩子函数来执行自定义逻辑,并最终返回一个已经完全初始化完毕的 `DefaultListableBeanFactory` 实对象[^2]。该工厂主要承担两方面职责:一是管理所有已知类型的 Beans;二是依据需求动态生成新的实。 #### 4. 特殊 Bean 处理 随后,Spring 开始扫描整个上下文中是否存在某些预定义好的特殊种类 beans (比如事件监听者、AOP代理等等)。如果发现有此类 bean 存在于当前环境中,则进一步激活它们的相关特性以增强框架的功能性。 #### 5. 应用级服务准备 最后一步就是实际创建那些被标记为模式下的 beans 并建立好相互之间必要的依赖注入关系。至此为止,整个 spring application context 已经处于可用状态,随时等待外部请求的到来。 #### 关键点补充 - 事务管理机制 值得注意的是,在上述整体流程之外还有一个非常重要的组成部分——即事务管理的支持。Spring 提供了一个统一而灵活的抽象层用于处理来自不同平台上的本地或全局性的交易控制行为[^4]。这意味着开发者无需关心具体的技术细节就可以轻松实现复杂的业务场景下的一致性和可靠性保障。 ```java // 示代码展示如何简配置事务管理器 @Configuration @EnableTransactionManagement public class TransactionConfig { @Bean public DataSource dataSource() { EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); return builder.setType(EmbeddedDatabaseType.HSQL).build(); } @Bean public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } } ``` 以上便是关于 Spring Framework 初始话全过程的一个概览描述及其背后涉及到的一些核心概念和技术要点说明。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

融极

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值