目录

1. synchronized 加锁

2. 初始化前的预处理prepareRefresh

2.1 系统默认逻辑

2.2 initPropertySources

2.3 validateRequiredProperties 

3. 初始化BeanFactory——obtainFreshBeanFactory

3.1 XML驱动(传统Spring)

3.2注解驱动方式(SpringBoot默认)

4. 预处理BeanFactory——prepareBeanFactory

4.1 ApplicationContextAwareProcessor

4.2 ignoreDependencyInterface

4.3 registerResolvableDependency

5. BeanFactory的后置处理器—— postProcessBeanFactory

5.1 SpringBoot中的默认实现

5.2 Web场景下的子类重写示例(Servlet 相关处理器 + Web 作用域)

6. 执行后置处理器——invokeBeanFactoryPostProcessor

6.1 BeanDefinitionRegistryPostProcessor

6.2 ConfigurationClassPostProcessor

6.3 BeanFactoryPostProcessor

7. 初始化BeanFactory——registerBeanPostProcessors

8. 初始化国际化组件——initMessageSource

9. 初始化事件广播器——initApplicationEventMulticaster

10. 子类扩展初始化——onRefresh

11. 注册监听器—— registerListeners

12. 初始化所有单例 Bean——finishBeanFactoryInitialization

12.1 getBean整体流程

12.2 doCreateBean整体流程

12.2.1实例化Bean对象

12.2.2属性赋值前的收集

12.2.3早期bean对象引用的获取与缓存

12.2.4属性赋值与依赖注入

12.2.5 bean对象的初始化

12.2.6 循环依赖校验

12.3 单例初始化完成回调——SmartInitializingSingleton

12.4 循环依赖的处理

12.4.1循环依赖的产生

12.4.2 循环依赖的解决模型

12.4.3基于 setter/@Autowired 的循环依赖

12.4.4基于构造方法的循环依赖

12.4.5基于原型 Bean 的循环依赖

12.4.6引入AOP的额外设计

12.4.7循环依赖的重要注意事项

13. 刷新完成——finishRefresh

13.1初始化并获取生命周期处理器 LifecycleProcessor

13.2调用 LifecycleProcessor 的 onRefresh 方法

13.3发布容器启动完成事件

13.4清除上下文资源缓存


在讲解IOC容器的刷新之前,简单了解一下回调的概念。回调就是把一个方法 / 函数当作参数传给另一段逻辑,等后者执行到合适时机再反过来调用前者;其原理基于函数式引用与延迟执行,由被调用方在满足条件(如事件触发、任务完成、阶段结束)时主动执行传入的逻辑;作用是实现解耦、异步通知与生命周期扩展,让外部能在不修改核心流程的前提下介入关键点执行自定义逻辑。

在SpringBootApplication启动的代码中有一个refreshContext方法,即为IOC容器刷新的核心函数。

public class SpringApplication {

    /**
     * SpringBoot 启动核心方法
     * @param args 启动参数
     * @return 容器上下文
     */
    public ConfigurableApplicationContext run(String... args) {
        // 1. 创建计时器,记录启动耗时
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        // 2. 初始化引导上下文、环境配置
        DefaultBootstrapContext bootstrapContext = createBootstrapContext();
        //3.运行时环境创建、触发与 SpringApplication 绑定
        ConfigurableEnvironment environment = prepareEnvironment(bootstrapContext, args);
        // 4.允许Bean定义是否覆盖(默认关闭)
        configureIgnoreBeanInfo(environment);
        // 5. 打印Banner
        Banner printedBanner = printBanner(environment);
        // 5. 创建Spring容器(根据Web类型创建)
        ConfigurableApplicationContext context = createApplicationContext();
        // 6. 准备容器:设置环境、执行初始化器、注册主配置类
        prepareContext(bootstrapContext, context, environment, printedBanner);
       
 // *******刷新容器:扫描Bean、创建单例、自动配置****************
        refreshContext(context);

        // 7. 容器刷新后:执行Runner、启动完成回调
        afterRefresh(context, args);
        // 8. 停止计时器,输出启动日志
        stopWatch.stop();
        // 9. 返回容器
        return context;
    }


}

refreshContext的调用链如下

SpringApplication#refreshContext()
       ↓ 调用
SpringApplication#refresh(context)
       ↓ 调用
ConfigurableApplicationContext#refresh()
       ↓ 最终实现
AbstractApplicationContext#refresh()  ← 核心!

而AbstractApplicationContext内部的refresh逻辑如下

public abstract class AbstractApplicationContext {
    /**
     * Spring IOC 容器刷新核心方法
     * 完成:容器初始化、Bean 加载、创建、依赖注入、自动配置、启动
     */
    @Override
    public void refresh() throws IllegalStateException {
        // 1. 加锁,保证线程安全
        synchronized (this.startupShutdownMonitor) {
            // 2. 刷新前预处理:标记启动时间、激活状态、初始化环境
            prepareRefresh();
            // 3. 获取 Bean 工厂:创建/刷新 BeanFactory,加载所有 BeanDefinition
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            // 4. 准备 Bean 工厂:配置类加载器、环境、SpEL 解析器、系统级 Bean
            prepareBeanFactory(beanFactory);
            try {
                // 5. Bean 工厂后置处理【**扩展点**】:子类可修改 BeanFactory 属性、注册 Bean
                postProcessBeanFactory(beanFactory);
                // 6. 执行 BeanFactory 后置处理器【**核心扩展点**】:执行 ConfigurationClassPostProcessor,完成配置类解析、自动配置、BeanDefinition 加载
                invokeBeanFactoryPostProcessors(beanFactory);
                // 7. 注册 Bean 后置处理器【**扩展点**】:注册 BeanPostProcessor,用于拦截 Bean 创建、实现 AOP、依赖注入增强
                registerBeanPostProcessors(beanFactory);
                // 8. 初始化国际化信息:初始化 MessageSource 用于国际化
                initMessageSource();
                // 9. 初始化事件广播器:初始化事件发布器,用于事件发布与监听器通知
                initApplicationEventMulticaster();
                // 10. 子类扩展初始化【**扩展点**】:Web 容器在此启动 Tomcat/Jetty
                onRefresh();
                // 11. 注册监听器【**扩展点**】:注册 ApplicationListener,响应容器事件
                registerListeners();
                // 12. 【核心】初始化所有单例 Bean:完成 Bean 实例化、依赖注入、初始化方法执行、AOP 代理
                finishBeanFactoryInitialization(beanFactory);
                // 13. 刷新完成:发布容器刷新完成事件,启动完成
                finishRefresh();
            } catch (RuntimeException ex) {
                throw ex;
            }
        }
    }
}

1. synchronized 加锁

startupShutdownMonitor 是 AbstractApplicationContext 中专用于线程同步的私有常量 Object 对象,不承担任何业务逻辑,仅作为独立、无侵入的监视器锁,保护 IOC 容器 refresh() 刷新和 destroy() 销毁的生命周期安全;synchronized (this.startupShutdownMonitor) 基于该对象实现互斥锁机制,同一时刻只允许一个线程执行刷新 / 关闭逻辑,具备轻量、可重入、线程安全的特点,能避免多线程并发导致的容器状态错乱、Bean 重复创建、资源竞争问题;此处使用 synchronized 而非其他锁,是因为它JVM 原生支持、无需额外依赖、实现简单稳定,足以满足容器生命周期的串行执行需求

2. 初始化前的预处理prepareRefresh

prepareRefresh 主要完成容器状态标记、早期事件集合初始化,并提供 initPropertySources() 扩展点与必选属性校验能力,前者用于自定义配置扩展,后者用于强制校验关键配置。

protected void prepareRefresh() {
    // 系统默认:记录启动时间、设置容器为激活状态
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);
    // 系统默认:初始化早期事件集合,暂存刷新完成前的事件
    this.earlyApplicationEvents = new LinkedHashSet<>();
    // 【可扩展】子类自定义属性源初始化,默认空实现
    initPropertySources();
    // 【可配置】校验必填属性是否存在
    getEnvironment().validateRequiredProperties();
}

2.1 系统默认逻辑

主要做容器状态标记、启动时间记录,并初始化 earlyApplicationEvents 集合,用于暂存容器完全初始化前发布的早期事件,这部分是固定逻辑,无需也不能修改。

2.2 initPropertySources

【可扩展点】空实现方法,允许子类重写,用于自定义加载 / 校验配置源、设置环境属性、激活自定义配置模式,是 Spring 容器暴露的标准扩展入口。一般很少用,只有需要在容器极早期自定义配置源时才会用到,普通项目几乎不使用。

public class MyApplicationContext extends AnnotationConfigApplicationContext {
    @Override
    protected void initPropertySources() {
        // 自定义添加配置源
        getEnvironment().getPropertySources().addLast(new MapPropertySource("customSource",
                Collections.singletonMap("custom.key", "custom.value")));
    }
}

2.3 validateRequiredProperties 

【可人为配置点】校验环境中人为标记的必选属性是否存在,可通过 environment.setRequiredProperties() 指定必须配置的参数,未配置时容器启动直接报错。偶尔使用多用于多环境部署、微服务启动校验,确保关键配置不缺失。

public static void main(String[] args) {
    SpringApplication app = new SpringApplication(App.class);
    app.addApplicationContextInitializer(ctx -> {
        // 标记 app.id 为必填属性
        ctx.getEnvironment().setRequiredProperties("app.id");
    });
    app.run(args);
}

3. 初始化BeanFactory——obtainFreshBeanFactory

obtainFreshBeanFactory 是 Spring 容器刷新的第三步,核心作用是创建全新的 BeanFactory,并根据配置方式(XML 或注解)加载并注册所有 BeanDefinition,为后续 Bean 实例化提供基础;该方法本身无扩展点,仅提供模板流程,真正的加载逻辑由子类实现,XML 驱动与注解驱动的加载方式、实现类、配置格式完全不同,且现代项目几乎全部使用注解驱动。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 刷新 BeanFactory(XML/注解子类各自实现)
    refreshBeanFactory();
    // 返回已加载好 BeanDefinition 的工厂
    return getBeanFactory();
}

XML 驱动依靠配置文件加载 Bean,老旧、低效、几乎不用;注解驱动依靠配置类与包扫描自动加载 Bean,高效、可扩展、SpringBoot 默认使用,两者底层 BeanFactory 完全一致。

3.1 XML驱动(传统Spring)

XML 驱动通过 ClassPathXmlApplicationContext 实现,底层使用 XmlBeanDefinitionReader 解析 XML 配置文件,读取 <bean> 标签生成 BeanDefinition 并注册到 DefaultListableBeanFactory,整个过程基于配置文件完成 Bean 定义加载,属于 Spring 早期标准方式,无需要手动扩展的核心点,仅需指定 XML 路径即可,目前仅用于老旧项目维护,使用频率极低。

// XML 驱动完整启动方式
public class SpringXmlApplication {
    public static void main(String[] args) {
        // 加载 XML 配置,内部自动执行 obtainFreshBeanFactory 创建 BeanFactory
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = context.getBean(UserService.class);
        userService.test();
        context.close();
    }
}

// XML 配置示例 applicationContext.xml
/*
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans">
    <bean id="userService" class="com.example.service.UserService"/>
</beans>
*/

// Bean 类
class UserService {
    public void test() {
        System.out.println("XML 方式加载 Bean");
    }
}

// DefaultListableBeanFactory 内部序列化ID(固定)
// private static final long serialVersionUID = 1L;

3.2注解驱动方式(SpringBoot默认)

注解驱动是 SpringBoot 唯一使用方式,基于 AnnotationConfigApplicationContext 实现,通过 AnnotatedBeanDefinitionReader 读取 @Configuration 配置类、执行 @ComponentScan 包扫描,自动识别 @Service/@Component/@Bean 完成 BeanDefinition 注册可扩展点极强,常用扩展包括指定扫描包、注册配置类、自定义 BeanName 生成器,是现代企业项目唯一使用方案,使用频率极高。不过注意,这些动作仅仅是把配置类、扫描路径记录到容器中,真正解析是在后面1.6中的inokeBeanFactoryPostProceser。

// 注解驱动完整启动方式
@SpringBootApplication
public class SpringAnnotationApplication {
    public static void main(String[] args) {
        // 注解容器内部执行 obtainFreshBeanFactory 创建 BeanFactory
        ConfigurableApplicationContext context = SpringApplication.run(SpringAnnotationApplication.class, args);
        UserService userService = context.getBean(UserService.class);
        userService.test();
        context.close();
    }
}

// 注解 Bean
@Service
class UserService {
    public void test() {
        System.out.println("注解方式加载 Bean");
    }
}

// 扩展示例:自定义扫描包(常用)
/*
@ComponentScan(basePackages = "com.example.service")
@Configuration
public class AppConfig {}
*/

// DefaultListableBeanFactory 内部序列化ID(官方固定)
// private static final long serialVersionUID = 1L;

4. 预处理BeanFactory——prepareBeanFactory

prepareBeanFactory 是 Spring 容器刷新的核心基础配置方法,负责对刚创建的 DefaultListableBeanFactory 进行全面初始化配置类加载器、SpEL 表达式解析器、属性编辑器,并注册ApplicationContextAwareProcessor、ApplicationListenerDetector等关键后置处理器,同时配置自动注入忽略规则、系统级依赖映射与环境相关单例 Bean;该方法绝大部分逻辑为系统固定流程,仅提供少量底层扩展点。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 基础配置(类加载器、SpEL、属性编辑器)——系统默认
    beanFactory.setBeanClassLoader(getClassLoader());
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 注册 ApplicationContextAwareProcessor —— 处理所有Aware接口
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

    // 忽略Aware接口的自动注入(避免重复注入)——系统默认
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

    // 注册可自动注入的系统Bean(Environment、ApplicationContext等)——系统默认
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    //注册 ApplicationListenerDetector —— 检测监听器Bean
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    //处理LoadTimeWeaver(AOP类加载期织入)——系统默认(极少用)
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getClassLoader()));
    }

    // 注册环境相关单例(systemProperties、systemEnvironment)——系统默认
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

4.1 ApplicationContextAwareProcessor

Spring 内置的 Bean 后置处理器,在 prepareBeanFactory 中直接注册,核心作用是在 Bean 初始化前回调所有 Aware 接口为业务 Bean 注入容器相关资源,包括 ApplicationContextAware、EnvironmentAware、ResourceLoaderAware 等,使普通 Bean 能够获取 Spring 容器、环境变量、配置文件等系统资源,无需硬编码获取,该组件为框架固定组件,不可替换,仅需实现对应 Aware 接口即可使用,使用频率极高,是 Spring 框架内置的核心能力。

4.2 ignoreDependencyInterface

自动注入忽略规则,ignoreDependencyInterface 用于配置 Spring 自动注入时忽略指定接口,避免 @Autowired 等注解对 Aware 类型接口进行重复注入,Aware 接口的注入统一由 ApplicationContextAwareProcessor 处理,而非依赖自动注入,该配置为系统内置固定规则,包含 ApplicationContextAware、EnvironmentAware 等,仅支持框架底层扩展,业务项目几乎不使用,使用频率极低。

4.3 registerResolvableDependency

系统依赖注册,registerResolvableDependency 用于向容器注册全局可直接注入的系统级对象,包括 ApplicationContext、Environment、ResourceLoader、ApplicationEventPublisher业务 Bean 可直接使用 @Autowired 注入这些对象,无需手动创建,该配置为系统固定逻辑,保证核心系统对象全局可访问,使用频率极高,是 Spring 最常用的基础能力之一。

// 业务类直接注入系统对象
@Service
public class MyService {
    // 由 prepareBeanFactory 注册,可直接注入
    @Autowired private Environment environment;
    @Autowired private ApplicationContext applicationContext;
    public void test() {
        System.out.println(environment.getProperty("spring.application.name"));
    }
}

ApplicationListenerDetector 组件

ApplicationListenerDetector 是 Spring 用于自动检测并注册事件监听器的后置处理器在 prepareBeanFactory 中注册,它会扫描所有 Bean,识别实现 ApplicationListener 接口的监听器 Bean,标记其类型并在 Bean 初始化完成后自动注册到容器的事件广播器中,实现事件监听能力,该组件为系统固定组件,无需手动配置,只要定义 ApplicationListener 类型 Bean 即可被自动识别,是 Spring 事件驱动模型的核心组件,使用频率极高。

// 自定义监听器,无需注册,由 ApplicationListenerDetector 自动检测注册
@Component
public class MyListener implements ApplicationListener<ApplicationEvent> {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("收到事件:" + event.getClass().getSimpleName());
    }
}

LoadTimeWeaverAwareProcessor 组件

LoadTimeWeaverAwareProcessor 是 Spring 用于类加载期 AOP 织入的后置处理器,在 prepareBeanFactory 中按需注册仅当容器中存在 loadTimeWeaver Bean 时才会生效,主要用于 AspectJ 运行时织入、动态类加载等底层框架功能,属于企业级底层扩展组件,普通 SpringBoot 项目几乎不会使用,使用频率极低。

// 启用类加载期织入(极少使用,框架级配置)
@Configuration
@EnableLoadTimeWeaving
public class LoadTimeWeaverConfig {
    // 容器会自动注册 LoadTimeWeaver 并触发处理器注册
}

 环境单例注册(systemProperties /systemEnvironment)

prepareBeanFactory 会自动注册 systemProperties 和 systemEnvironment 两个单例 Bean,将 JVM 系统属性与操作系统环境变量暴露到 Spring 容器中,可直接注入使用,该逻辑为系统固定流程,无需任何配置,是 Spring 环境适配的基础能力,使用频率高。

// 直接注入系统环境变量
@Component
public class SystemEnvBean {
    @Autowired private Map<String, Object> systemProperties;
    @Autowired private Map<String, Object> systemEnvironment;
    public void print() {
        System.out.println(systemProperties.get("java.version"));
    }
}

5. BeanFactory的后置处理器—— postProcessBeanFactory

5.1 SpringBoot中的默认实现

postProcessBeanFactory 是 Spring 容器刷新流程中,标准的、安全的工厂后置处理扩展点。在通用抽象容器 AbstractApplicationContext 中,它默认是空实现,不执行任何系统逻辑,只留给子类去扩展,用于在 Bean 实例化之前对 BeanFactory 做最终定制,比如注册特殊后置处理器、添加作用域、修改注入规则等。整体上,该方法属于 “框架内置扩展 + 用户自定义扩展” 共用的阶段,系统默认行为极少,可干预空间很大。

public abstract class AbstractApplicationContext {
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 通用版本:空实现,留给子类扩展
        // Spring 最基础、最通用的行为,不包含 Web、不包含扫描、不包含任何自动配置。
    }
}

5.2 Web场景下的子类重写示例(Servlet 相关处理器 + Web 作用域)

虽然顶层设计是空白模板,但在 SpringBoot Web 环境中,实际使用的 ServletWebServerApplicationContext 会重写该postProcessBeanFactory 方法,用于完成 Web 环境所需的全部初始化工作,包括回调父类扩展、注册 Servlet 上下文处理器、注册 Web 作用域、注册 Web 环境 Bean、执行注解扫描与配置类解析。

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 1. 回调父类方法,保证上层扩展逻辑不丢失(必须执行)
    super.postProcessBeanFactory(beanFactory);
    // 2. 注册 ServletContextAwareProcessor,用于注入 ServletContext、ServletConfig
    beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.getServletContext()));
    // 3. 忽略 Web 相关 Aware 接口,避免重复注入
    beanFactory.ignoreDependencyInterface(ServletContextAware.class);
    beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
    // 4. 注册 Web 应用三大作用域:request、session、application
    WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.getServletContext());
    // 5. 注册 Web 环境 Bean(ServletContext、ServletConfig 可自动注入)
    WebApplicationContextUtils.registerEnvironmentBeans(
        beanFactory, this.getServletContext(), this.getServletConfig()
    );
    // 6. 执行注解扫描:扫描 @Component、@Service、@Controller 等
    if (!this.basePackages.isEmpty()) {
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanFactory);
        scanner.scan(this.basePackages.toArray(new String[0]));
    }
    // 7. 解析并注册手动传入的配置类(@Configuration 类)
    if (!this.registrants.isEmpty()) {
        AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(beanFactory);
        for (Class<?> configClass : this.registrants) {
            reader.register(configClass);
        }
    }
}

值得注意的是, registerWebApplicationScopes 这个方法。该方法完成Web 作用域(request/session/application)的安全注册,并专门设计 ExistingWebApplicationScopes 机制来保存并恢复已存在的作用域,这是为了完美适配 Jar 包内嵌 Web 容器的启动时序问题在 Jar 打包运行时,Spring 上下文刷新 refresh() 会早于 Tomcat/Jetty 等内嵌服务器初始化,此时 ServletContext 尚未创建,传统 Web 作用域无法直接依赖实体容器对象,因此 Spring 采用延迟作用域 + 代理模式预先注册 request、session 等作用域,使其能够先被解析、等待后续 Web 容器启动后再真正绑定;同时 ExistingWebApplicationScopes 会在注册默认作用域前,先把容器中已存在的同名作用域保存起来,等框架注册完默认 Web 作用域后再将用户或第三方框架自定义的作用域恢复回去,确保自定义作用域不会被系统默认作用域覆盖,保证优先级与兼容性。

// 核心方法:注册 Web 作用域 + 保存恢复已存在作用域
private void registerWebApplicationScopes() {
    // 1. 创建保存器,先把当前已有的 request/session/application 作用域存起来
    ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(getBeanFactory());
    
    try {
        // 2. 注册 Spring 自带的默认 Web 作用域(request、session、application)
        // 即使 ServletContext 为 null(内嵌容器未启动),也能安全注册
        WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory(), getServletContext());
    } finally {
        // 3. 恢复之前保存的自定义作用域,不覆盖用户配置
        existingScopes.restore();
    }
}

// 保存/恢复已存在作用域的内部类(SpringBoot 3.x 最新源码)
private static class ExistingWebApplicationScopes {
    private final ConfigurableListableBeanFactory beanFactory;
    private final Map<String, Scope> scopes = new HashMap<>();

    // 构造时:保存已有的 Web 作用域,避免丢失
    ExistingWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
        // 把 request、session、application 等作用域先暂存起来
        for (String scopeName : WebApplicationContextUtils.SCOPE_NAMES) {
            Scope existingScope = beanFactory.getRegisteredScope(scopeName);
            if (existingScope != null) {
                this.scopes.put(scopeName, existingScope);
            }
        }
    }

    // 恢复:把用户自定义作用域重新注册回去,优先级高于默认
    public void restore() {
        this.scopes.forEach((name, scope) -> this.beanFactory.registerScope(name, scope));
    }
}

// 系统默认 Web 作用域注册(底层工具类)
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory, ServletContext servletContext) {
    // 注册 request 作用域(基于 ThreadLocal 延迟实现,不依赖容器启动)
    beanFactory.registerScope(SCOPE_REQUEST, new RequestScope());
    // 注册 session 作用域
    beanFactory.registerScope(SCOPE_SESSION, new SessionScope());
    // 注册 application 作用域(依赖 ServletContext,容器启动后自动绑定)
    beanFactory.registerScope(SCOPE_APPLICATION, new ServletContextScope(servletContext));
}

6. 执行后置处理器——invokeBeanFactoryPostProcessor

invokeBeanFactoryPostProcessors 是 Spring 容器刷新最核心的扩展阶段之一。它负责按固定优先级顺序执行所有 BeanFactory 后置处理器,在所有 Bean 实例化之前对 BeanDefinition(Bean 定义信息)进行最终修改、注册、删除、配置所有配置类解析、配置文件加载、自动配置、动态注册 Bean 都在这一步完成。执行顺序严格遵循:内置处理器 → 手动注册处理器 → 标注 @Component 的处理器 → 按优先级 / 排序执行。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 1. 执行 Spring 内置的、手动传入的 BeanFactoryPostProcessor
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}

后置处理器完整的执行顺序为

执行手动注册的 BeanDefinitionRegistryPostProcessor
执行实现 PriorityOrdered的 BeanDefinitionRegistryPostProcessor
执行实现 Ordered的 BeanDefinitionRegistryPostProcessor
执行剩余所有 BeanDefinitionRegistryPostProcessor
执行手动注册的 BeanFactoryPostProcessor
执行实现 PriorityOrdered的 BeanFactoryPostProcessor
执行实现 Ordered的 BeanFactoryPostProcessor
执行剩余所有的 BeanFactoryPostProcessor

6.1 BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessor是优先级最高的工厂后置处理器,继承自 BeanFactoryPostProcessor,专门用于动态注册、移除 BeanDefinition,它的执行时机早于所有普通工厂后置处理器,是 Spring 实现动态装配、框架扩展的核心接口。Spring 会先收集所有该类型处理器,按优先级分批执行,确保核心系统处理器优先工作,完成 Bean 定义的补充与扩展。

BeanDefinitionRegistryPostProcessor 属于框架级扩展接口,基于它可以在容器启动阶段动态注册全新的 BeanDefinition,主要用于插件化开发、模块化加载、ORM 框架集成(如 MyBatis Mapper 扫描)以及中间件组件的自动装配等场景,这类扩展在普通业务项目中几乎不会使用,因为动态注册会让 Bean 的来源变得不透明,提升了项目的维护复杂度。

6.2 ConfigurationClassPostProcessor

SpringBoot最核心组件,ConfigurationClassPostProcessor 是 Spring 内置最高优先级的BeanDefinitionRegistryPostProcessor,也是整个注解驱动的基石,在本阶段第一批执行。它会全面解析所有 @Configuration 配置类,处理 @ComponentScan 完成包扫描,解析 @Bean 方法生成 BeanDefinition,处理 @Import 加载自动配置,同时判断 @Conditional 条件是否生效,SpringBoot 全部自动配置均由此处理器加载,所有 Bean 定义最终由此组件定型

6.3 BeanFactoryPostProcessor

所有 BeanDefinitionRegistryPostProcessor 执行完毕后,Spring 开始执行普通 BeanFactoryPostProcessor,这类处理器不负责注册新的 BeanDefinition,专注于修改已存在的 Bean 定义例如设置懒加载、修改作用域、调整依赖关系、覆盖属性等,执行顺序同样遵循优先级规则,是容器完成 Bean 定义加载后的最后修改机会

用户自定义的 BeanFactoryPostProcessor 是业务开发中最常用的扩展方式,只需实现该接口并使用 @Component 注解将其纳入容器管理,即可在 Bean 实例化之前对已注册的 BeanDefinition 进行统一修改。这种扩展方式对容器底层无侵入,安全性高且易于控制,是 Spring 官方推荐的业务扩展方案。

7. 初始化BeanFactory——registerBeanPostProcessors

registerBeanPostProcessors 核心职责是提前发现、排序、注册所有 BeanPostProcessor(Bean 后置处理器),但不执行处理器逻辑。这一步会从已加载的 BeanDefinition 中找出所有实现 BeanPostProcessor 接口的 Bean,将它们实例化,并按 PriorityOrdered、Ordered、普通处理器的顺序排序,最终注册到 BeanFactory 的处理器列表中,为后续 Bean 实例化、依赖注入、初始化时的拦截增强做准备。所有后续 Bean 创建时的依赖注入、生命周期回调、AOP 代理、Aware 注入,都依赖这一步提前注册好的处理器。

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

注意:6. invokeBeanFactoryPostProcessors 执行的是 工厂后置处理器(BeanFactoryPostProcessor),它的作用是修改、注册 BeanDefinition。而这里的registerBeanPostProcessors 处理的是 Bean 后置处理器(BeanPostProcessor),它的作用是拦截 Bean 创建、做依赖注入、AOP、生命周期。

registerBeanPostProcessors内部执行流程如下。

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

    // 1. 找出所有 BeanPostProcessor 的名称(只找名字,不实例化)
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    List<BeanPostProcessor> priorityOrderedProcessors = new ArrayList<>();
    List<BeanPostProcessor> orderedProcessors = new ArrayList<>();
    List<BeanPostProcessor> nonOrderedProcessors = new ArrayList<>();

    // 2. 分类:按 PriorityOrdered / Ordered / 普通 分组
    for (String ppName : postProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        if (pp instanceof PriorityOrdered) {
            priorityOrderedProcessors.add(pp);
        } else if (pp instanceof Ordered) {
            orderedProcessors.add(pp);
        } else {
            nonOrderedProcessors.add(pp);
        }
    }

    // 3. 排序
    sort(priorityOrderedProcessors);
    sort(orderedProcessors);

    // 4. 注册到 BeanFactory(按优先级顺序加入)
    registerBeanPostProcessors(beanFactory, priorityOrderedProcessors);
    registerBeanPostProcessors(beanFactory, orderedProcessors);
    registerBeanPostProcessors(beanFactory, nonOrderedProcessors);

    // 5. 注册内部检查器:BeanPostProcessorChecker
    BeanPostProcessorChecker checker = new BeanPostProcessorChecker(beanFactory, postProcessorNames.length + 1);
    registerBeanPostProcessors(beanFactory, Collections.singletonList(checker));
}

// 注册工具方法
private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> processors) {
    for (BeanPostProcessor processor : processors) {
        beanFactory.addBeanPostProcessor(processor);

        // 特殊处理:MergedBeanDefinitionPostProcessor 单独记录(用于提前修改Bean定义)
        if (processor instanceof MergedBeanDefinitionPostProcessor) {
            beanFactory.addMergedBeanDefinitionPostProcessor((MergedBeanDefinitionPostProcessor) processor);
        }
    }
}

其中MergedBeanDefinitionPostProcessor 是 BeanPostProcessor 的特殊子类型,在 Bean 实例化之前、BeanDefinition 合并之后执行,用于提前扫描并缓存 @Autowired、@Resource、@PostConstruct 等注解元数据,是 Spring 依赖注入能够实现的核心支撑。
BeanPostProcessorChecker 是 Spring 内部最后注册的检查处理器,不做任何功能增强,只用于监控容器启动状态,发现并警告那些提前实例化、可能无法被正常增强的 Bean,保证启动稳定性。

8. 初始化国际化组件——initMessageSource

initMessageSource 用于初始化 Spring 的国际化支持组件 MessageSource,它负责加载不同语言的配置文件(如 messages_zh_CN.properties),实现提示信息、异常信息的多语言切换。执行时机在所有 BeanPostProcessor 注册完成之后、容器完全启动之前。Spring 默认会自动寻找名为 messageSource 的 Bean,不存在时则使用空实现的静态消息源。这是系统固定初始化逻辑,扩展点为自定义 MessageSource Bean,适用于需要国际化的 Web、APP 后台项目,普通项目极少使用。

9. 初始化事件广播器——initApplicationEventMulticaster

 initApplicationEventMulticaster 用于初始化 Spring 的事件派发器 ApplicationEventMulticaster,它负责管理所有事件监听器,并在事件发布时将事件同步 / 异步广播给对应的监听器。执行时机紧跟国际化初始化之后。容器默认使用 SimpleApplicationEventMulticaster,扩展点为自定义异步事件广播器,可通过定义 applicationEventMulticaster Bean 实现事件异步派发。该组件是 Spring 事件驱动机制的核心,扩展频率低,多用于高并发、异步事件处理场景

10. 子类扩展初始化——onRefresh

onRefresh() 是 Spring 预留的空方法扩展点,模板方法设计模式的典型应用,执行时机在事件广播器初始化之后、单例 Bean 实例化之前。SpringBoot 内置容器会重写该方法实现核心扩展:SpringBoot Web 容器在这一步启动内嵌 Tomcat/Jetty,创建 Web 服务器并初始化 ServletContext。这是 Spring 提供的顶级安全扩展点,用户可重写该方法实现容器刷新后的自定义初始化逻辑。执行时机极早、扩展价值极高,普通业务项目很少使用,框架、Starter、中间件常用。

11. 注册监听器—— registerListeners

registerListeners 的作用是向容器注册所有事件监听器,并将其绑定到上一步初始化的事件广播器 ApplicationEventMulticaster 上,以便容器在发布事件时,能够正确通知到对应的监听器。执行时机在容器刷新后期、单例 Bean 实例化之前,是 Spring 事件驱动模型的关键注册环节。

protected void registerListeners() {
    // 1. 注册手动通过代码添加的监听器
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // 2. 从容器中找到所有实现了ApplicationListener接口的Bean
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }
}

12. 初始化所有单例 Bean——finishBeanFactoryInitialization

Spring 容器最核心、最复杂的一步:实例化所有非懒加载单例 Bean、完成依赖注入、初始化、AOP 代理

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 1. 初始化 ConversionService 类型转换
    if (beanFactory.hasConversionService()) {
        beanFactory.getConversionService();
    }
    // 2. 冻结所有 BeanDefinition(不允许再修改)
    beanFactory.freezeConfiguration();
    // 3. 实例化 所有 非懒加载 单例 Bean(真正核心)
    beanFactory.preInstantiateSingletons();
}

初始化所有单例的总方法,包含:遍历 → 筛选 → getBean → 事件触发。

public void preInstantiateSingletons() throws BeansException {
    // 1. 获取所有 Bean 名称
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    // 2. 遍历所有 Bean,初始化非懒加载单例
    for (String beanName : beanNames) {
        // 2.1 获取合并后的 BeanDefinition
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        // 2.2 条件:非抽象 + 单例 + 非懒加载
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            // 2.3 跳过 FactoryBean(后续单独处理)
            if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            } else {
                // 2.4 【关键】正常 Bean → 触发创建
                getBean(beanName);
            }
        }
    }
    // 3. 调用单例初始化完成回调
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {
            smartSingleton.afterSingletonsInstantiated();
        }
    }
}

12.1 getBean整体流程

别名解析 → 单例检查 → 循环依赖处理 → 标记创建 → 父容器检查 → 真正创建

protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) {
    // 1. 别名解析
    String beanName = transformedBeanName(name);

    // 2. 从单例缓存获取(解决循环依赖)
    Object sharedInstance = getSingleton(beanName);

    if (sharedInstance != null && args == null) {
        // 3. 已创建 → 直接返回
        return (T) getObjectForBeanInstance(sharedInstance, name, beanName, null);
    } else {
        // 4. 创建前检查:原型循环依赖直接报错
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // 5. 标记 Bean 正在创建
        beforePrototypeCreation(beanName);
        try {
            // 6. 【真正创建 Bean】
            if (mbd.isSingleton()) {
                // 单例模式创建(带三级缓存)
                sharedInstance = getSingleton(beanName, () -> {
                    return createBean(beanName, mbd, args);
                });
            } else if (mbd.isPrototype()) {
                // 原型模式:每次创建新对象
                sharedInstance = createBean(beanName, mbd, args);
            }
        } finally {
            // 7. 清除创建标记
            afterPrototypeCreation(beanName);
        }
        return (T) sharedInstance;
    }
}

12.2 doCreateBean整体流程

调用链:getBean → doGetBean→createBean → doCreateBean

doCreateBean主要做的事情为:实例化 → 填充属性 → 初始化 → 代理

// 来源:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) {
    BeanWrapper instanceWrapper = null;
    // 1. 实例化Bean对象
    instanceWrapper = createBeanInstance(beanName, mbd, args);
    Object bean = instanceWrapper.getWrappedInstance();
    // 2. 早期bean对象引用的获取与缓存
    boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName);
    if (earlySingletonExposure) {
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }
    // 3. 属性赋值与依赖注入
    populateBean(beanName, mbd, instanceWrapper);
    // 4. bean对象的初始化
    Object exposedObject = initializeBean(beanName, bean, mbd);
    // 5. 循环依赖校验
    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            exposedObject = earlySingletonReference;
        }
    }
    return exposedObject;
}

12.2.1实例化Bean对象

该步骤由 createBeanInstance 完成,是 Bean 生命周期中创建原始对象的核心环节。

流程分为四个小点:解析 bean 对象的类型,工厂方法创建,原型 Bean 的创建优化,实例化 bean 对象的真实动作

解析 bean 对象的类型:Spring 会将 BeanDefinition 中的类名解析为 Class 对象,处理类加载、动态代理类等场景,这是实例化的前提,是整个 Bean 创建的基础,若类无法加载则直接抛出异常。

工厂方法创建:支持两种方式,一是 instanceSupplier 函数式接口,直接提供对象创建逻辑,二是 factoryMethod 工厂方法,调用指定类的静态 / 实例方法创建对象,这是 Spring 除了构造器反射外的核心扩展点

原型 Bean 的创建优化:原型作用域的 Bean 不会走缓存,每次都会执行完整的实例化逻辑,Spring 针对原型 Bean 做了简化处理,跳过循环依赖相关的缓存逻辑,提升创建效率。

实例化 bean 对象的真实动作:通过反射调用构造方法创建原始对象,此时对象仅完成实例化,未进行任何属性注入和初始化,是一个空对象。

// 来源:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
    // 1. 解析bean对象的类型
    Class<?> beanClass = resolveBeanClass(mbd, beanName);

    // 2. 工厂方法创建(instanceSupplier / factoryMethod)
    if (mbd.getInstanceSupplier() != null) {
        return obtainFromSupplier(mbd.getInstanceSupplier(), beanName);
    }
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
    // 3. 原型Bean无缓存优化,直接执行构造器实例化
    // 4. 实例化bean对象的真实动作:反射调用构造器
    BeanWrapper instanceWrapper = instantiateBean(beanName, mbd);
    // ================================
    // 【关键】这里执行注解后置处理器收集
    // ================================
    applyMergedBeanDefinitionPostProcessors(mbd, beanClass, beanName);

    return instanceWrapper;
}

12.2.2属性赋值前的收集

该步骤是实例化完成后、属性注入前的准备工作,由 MergedBeanDefinitionPostProcessor 系列处理器完成,调用链:createBeanInstance -> 后置处理器收集,这一步在实例化后立即执行,是注解驱动依赖注入的核心

核心处理器:InitDestroyAnnotationBeanPostProcessor 负责收集 @PostConstruct、@PreDestroy 生命周期注解;CommonAnnotationBeanPostProcessor 负责收集 @Resource 注解的注入点;AutowiredAnnotationBeanPostProcessor 负责收集 @Autowired、@Value 注解的注入点。这些处理器会将注解元数据缓存起来,为后续的属性注入和初始化做准备,是 Spring 实现注解式注入的底层支撑,属于框架核心扩展点,用户无需手动配置,Spring 自动注册。

12.2.3早期bean对象引用的获取与缓存

 Spring 解决单例 Bean 循环依赖的核心逻辑,仅针对单例 Bean 生效,调用链:doCreateBean -> addSingletonFactory -> getEarlyBeanReference。

判断条件:必须同时满足单例、允许循环依赖、当前 Bean 正在创建三个条件。满足后,Spring 会将当前原始对象包装为 ObjectFactory,存入三级缓存,getEarlyBeanReference 方法会执行后置处理器,提前生成 AOP 代理对象,保证循环依赖时注入的是代理对象而非原始对象。这是 Spring 解决循环依赖的唯一方式,仅单例支持,原型 Bean 会直接抛出循环依赖异常。

// 来源:DefaultSingletonBeanRegistry
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    synchronized (this.singletonObjects) {
        if (!this.singletonObjects.containsKey(beanName)) {
            // 存入三级缓存
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
        }
    }
}

12.2.4属性赋值与依赖注入

由 populateBean 方法完成,是依赖注入的核心执行环节。

核心流程分为四个小点:回调 InstantiationAwareBeanPostProcessor,自动注入的支持,回调 InstantiationAwareBeanPostProcessor,属性赋值。

第一次回调 InstantiationAwareBeanPostProcessor:执行 postProcessAfterInstantiation 方法,可通过实现该接口阻止后续的属性注入,是重要的扩展点

自动注入的支持:处理 byName、byType 自动注入模式,根据配置自动查找依赖对象,SpringBoot 中默认使用注解注入,该模式兼容传统 Spring 配置。

第二次回调 InstantiationAwareBeanPostProcessor:执行 postProcessProperties 方法,AutowiredAnnotationBeanPostProcessor 在此处完成 @Autowired 注解的依赖注入,是注解注入的执行时机。

属性赋值:将所有注入的属性设置到 Bean 对象中,完成依赖注入,此时 Bean 对象的属性全部填充完毕。

12.2.5 bean对象的初始化

由 initializeBean 方法完成,是 Bean 生命周期的最后核心环节。

核心流程分为四个步骤:invokeAwareMethods,applyBeanPostProcessorsBeforeInitialization,invokeInitMethods,applyBeanPostProcessorsAfterInitialization

invokeAwareMethods:执行 Aware 系列接口回调,包括 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware,让 Bean 感知自身的容器信息,是 Spring 提供的基础扩展点

applyBeanPostProcessorsBeforeInitialization:执行所有 BeanPostProcessor 的前置处理方法@PostConstruct 注解的方法在此处被执行,是常用的初始化扩展点

invokeInitMethods:执行 Bean 的初始化方法,优先级为 @PostConstruct > InitializingBean 接口的 afterPropertiesSet > 自定义 init-method 方法。

applyBeanPostProcessorsAfterInitialization:执行所有 BeanPostProcessor 的后置处理方法,Spring 的 AOP 代理在此处生成,是 AOP 实现的核心时机,也是最关键的框架扩展点

12.2.6 循环依赖校验

初始化完成后的收尾工作,仅针对开启了早期暴露的单例 Bean 执行。如果当前 Bean 参与了循环依赖,被其他 Bean 提前获取了早期引用,就将最终返回对象替换为二级缓存中的早期对象,保证整个容器中只有一个 Bean 实例,确保循环依赖场景下的对象唯一性,避免出现原始对象和代理对象不一致的问题。

12.3 单例初始化完成回调——SmartInitializingSingleton

该扩展接口在所有非懒加载单例 Bean 完全实例化、初始化、AOP 代理生成之后执行,调用链来自 preInstantiateSingletons 方法的末尾遍历逻辑。接口只有一个方法 afterSingletonsInstantiated,执行时机晚于 @PostConstruct、InitializingBean 等单个 Bean 的初始化回调,是整个容器启动阶段中,所有单例就绪后的最后一批扩展回调。使用方式为实现该接口并交给 Spring 管理,常用于项目启动后的全局数据加载、缓存预热、配置校验等场景,是业务中安全且常用的扩展点,不会出现因 Bean 未初始化完成导致的依赖问题。

// 来源:org.springframework.beans.factory.SmartInitializingSingleton
public interface SmartInitializingSingleton {
    void afterSingletonsInstantiated();
}
// 调用位置:DefaultListableBeanFactory#preInstantiateSingletons 末尾
for (String beanName : beanNames) {
    Object singletonInstance = getSingleton(beanName);
    if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {
        smartSingleton.afterSingletonsInstantiated();
    }
}

12.4 循环依赖的处理

12.4.1循环依赖的产生

循环依赖指两个或多个 Bean 之间相互依赖注入,形成闭环引用,在 Bean 创建过程中会出现需要对方但对方尚未创建完成的问题。典型场景为 A 依赖 B,B 依赖 A,在创建 A 时需要先创建 B,创建 B 时又需要 A,没有三级缓存机制就会无限递归并抛出异常,这是 Spring 容器启动中最常见的生命周期问题。

12.4.2 循环依赖的解决模型

Spring 仅支持单例 Bean 下的 setter 方式循环依赖,核心解决方案是三级缓存模型,调用链为 doCreateBean → addSingletonFactory → getSingleton。

一级缓存 singletonObjects 存放完全初始化好的成品 Bean,二级缓存 earlySingletonObjects 存放未完成属性注入和初始化的早期原始 Bean,三级缓存 singletonFactories 存放 ObjectFactory 函数式对象,用于提前生成 Bean 引用甚至 AOP 代理对象。Bean 实例化后立即放入三级缓存,被依赖时通过三级缓存获取早期对象,打破循环等待,完成创建后再移入一级缓存并清除其他缓存。

// 来源:DefaultSingletonBeanRegistry
private final Map<String, Object> singletonObjects;
private final Map<String, Object> earlySingletonObjects;
private final Map<String, ObjectFactory<?>> singletonFactories;

12.4.3基于 setter/@Autowired 的循环依赖

这是 Spring 唯一支持的循环依赖场景,执行流程为创建 A 实例化对象,将 A 工厂存入三级缓存,A 开始属性注入发现依赖 B,创建 B 实例化对象,将 B 工厂存入三级缓存,B 属性注入时从三级缓存获取早期 A 对象,B 完成初始化进入一级缓存,A 继续注入完整的 B 对象,A 完成初始化进入一级缓存。整个过程依靠三级缓存提前暴露半成品对象,不影响最终 Bean 唯一性,也是日常业务中最常见的循环依赖场景。

// 关键代码:doCreateBean 中提前暴露
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

12.4.4基于构造方法的循环依赖

构造方法注入的循环依赖 Spring 无法解决,因为实例化阶段就需要依赖对象,而此时还没有完成实例化,无法放入三级缓存,容器会直接抛出 BeanCurrentlyInCreationException 异常。该场景没有默认解决方案,只能通过 @Lazy 懒加载、拆分类结构、使用 setter 注入等方式规避,这是 Spring 生命周期的硬性限制。

12.4.5基于原型 Bean 的循环依赖

原型 Bean 每次获取都会创建新实例,不进入任何缓存,Spring 不会对原型 Bean 做循环依赖处理,一旦出现闭环依赖会直接抛出异常终止启动。原型 Bean 没有提前暴露机制,也没有缓存保存已创建实例,无法打破循环,业务设计中应严格避免原型 Bean 之间的相互依赖。

12.4.6引入AOP的额外设计

这是循环依赖与 AOP 代理的特殊处理, Spring 针对循环依赖场景下 AOP 代理的专门设计,也是高级核心知识点。正常情况下 AOP 代理在初始化完成后生成,但循环依赖时必须提前生成代理对象,否则注入的是原始对象而非代理对象。Spring 通过三级缓存中的 ObjectFactory 调用 getEarlyBeanReference 方法完成提前代理,该方法会执行 SmartInstantiationAwareBeanPostProcessor 处理器,直接生成早期代理对象并放入二级缓存,保证循环依赖中注入的始终是代理对象,与最终成品对象保持一致。这是 Spring 解决 AOP 加循环依赖场景的核心设计,没有这个逻辑,AOP 与循环依赖结合会出现对象不一致的严重问题。

// 来源:AbstractAutowireCapableBeanFactory
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    for (SmartInstantiationAwareBeanPostProcessor bp : getSmartInstantiationAwareBeanPostProcessors()) {
        // 这里提前生成 AOP 代理对象
        exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
    }
    return exposedObject;
}

12.4.7循环依赖的重要注意事项

只有单例 Bean 支持循环依赖,且必须是属性注入方式,构造器注入和原型作用域均不支持。开启 AOP 时代理对象依然能通过三级缓存正常获取,不会出现原始对象和代理对象不一致问题,核心依靠 getEarlyBeanReference 方法提前生成代理。循环依赖虽然可被解决,但属于不良设计,复杂项目中应尽量通过分层、抽象、事件驱动等方式避免。

13. 刷新完成——finishRefresh

 Spring 容器刷新的最后一步,标志着整个 IoC 容器初始化完毕,所有单例 Bean 创建完成,容器正式进入可用状态。该方法完成生命周期管理、启动组件、发布容器启动完成事件,是容器从 “初始化状态” 切换为 “运行状态” 的关键节点。

13.1初始化并获取生命周期处理器 LifecycleProcessor

Spring 会优先使用容器中自定义的 LifecycleProcessor Bean,不存在则使用默认的 DefaultLifecycleProcessor,它负责管理所有实现 Lifecycle 接口的 Bean 的启动与停止,是容器生命周期管理的核心组件。

// 调用链:finishRefresh -> initLifecycleProcessor -> getLifecycleProcessor
protected void initLifecycleProcessor() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean("lifecycleProcessor")) {
        this.lifecycleProcessor = beanFactory.getBean("lifecycleProcessor", LifecycleProcessor.class);
    } else {
        DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
        defaultProcessor.setBeanFactory(beanFactory);
        this.lifecycleProcessor = defaultProcessor;
    }
}

13.2调用 LifecycleProcessor 的 onRefresh 方法

触发容器内所有实现 Lifecycle 接口的 Bean 执行 start 启动逻辑,SpringBoot 中的内嵌服务器、定时任务、消息监听等组件都依靠这个机制启动,是容器加载后自动运行组件的核心扩展点

13.3发布容器启动完成事件

发布 ContextRefreshedEvent 事件,所有监听该事件的监听器会被触发,常用于容器启动后的业务初始化、数据加载、状态上报等操作,是业务开发中高频使用的扩展点。

13.4清除上下文资源缓存

完成最终初始化工作,标志着 Spring 应用上下文完全启动成功。

【注】:1.《SpringBoot源码解读与原理分析》LinkedBear著第七章阅读笔记,如果错误,欢迎指正

更多推荐