Spring容器的启动流程是一个复杂的过程,涉及多个阶段和组件的协作。核心是ApplicationContext
(如ClassPathXmlApplicationContext
、AnnotationConfigApplicationContext
等)接口的启动。通过对Spring启动流程的详细分析,可以更好地理解Spring是如何加载、解析、实例化、初始化并管理Bean的。
下面将详细描述Spring容器的启动流程,具体步骤如下:
1. 启动Spring容器
- Spring容器启动的第一步是创建
ApplicationContext
对象。ApplicationContext
是Spring容器的核心接口,代表了Spring上下文环境。常见的实现类有:ClassPathXmlApplicationContext
: 从类路径下的XML配置文件中加载Bean定义。AnnotationConfigApplicationContext
: 基于注解配置启动容器。FileSystemXmlApplicationContext
: 从文件系统中的XML配置文件中加载Bean定义。
2. 读取和解析配置文件
- Spring需要根据配置(XML文件、注解配置类等)加载Bean定义。Spring的
BeanDefinitionReader
负责解析这些配置。- 如果使用XML配置文件,
XmlBeanDefinitionReader
负责读取和解析配置文件,并将解析得到的Bean定义信息转换为BeanDefinition
对象。 - 如果使用注解配置类,
AnnotatedBeanDefinitionReader
负责扫描和解析注解,并注册Bean。
- 如果使用XML配置文件,
3. BeanDefinition的注册
- 解析Bean定义后,Spring会将每个Bean的定义信息以
BeanDefinition
形式注册到BeanFactory
中。BeanDefinition
包含了Bean的各种元数据,比如Bean的类类型、作用域(单例/原型)、是否需要懒加载、依赖关系等。 - 通过
DefaultListableBeanFactory
来管理和存储这些BeanDefinition
。
4. Spring容器刷新(refresh())
- 这是Spring启动过程中最核心的步骤。
ApplicationContext
的refresh()
方法会完成一系列操作,启动和初始化Spring容器:-
准备上下文环境:
- 设置上下文环境,包括配置资源(例如属性文件的读取),初始化一些特定的环境变量。
-
初始化BeanFactory:
- 创建或刷新
BeanFactory
,即完成对所有BeanDefinition
的解析和注册,形成一个完整的Bean定义列表。
- 创建或刷新
-
BeanFactory的后处理:
- 如果有
BeanFactoryPostProcessor
(比如PropertyPlaceholderConfigurer
),Spring会在这个阶段执行它们的回调,修改BeanDefinition
的定义或者其他元数据。
- 如果有
-
注册Bean后处理器(BeanPostProcessor):
- 注册所有实现
BeanPostProcessor
接口的类。这些处理器允许在Bean初始化前后进行拦截处理(如AOP代理、依赖注入后的处理等)。
- 注册所有实现
-
实例化和初始化单例Bean:
-
对所有非懒加载的单例Bean进行实例化和初始化。这里涉及到Bean的生命周期方法的调用,包括依赖注入、初始化方法的调用。
-
初始化时会依次执行以下几个步骤:
- 调用Bean的构造方法实例化。
- 通过
set
方法注入依赖。 - 如果Bean实现了
BeanNameAware
、BeanFactoryAware
等接口,会调用相应的方法。 - 如果有
BeanPostProcessor
,会在Bean初始化前后进行拦截处理。 - 执行Bean的初始化方法(如
@PostConstruct
或自定义的init-method
)。
-
-
初始化事件广播器(ApplicationEventMulticaster):
- 创建并初始化事件广播器,用于处理应用事件,如
ContextRefreshedEvent
等。
- 创建并初始化事件广播器,用于处理应用事件,如
-
注册事件监听器:
- 注册应用程序中的事件监听器(如果有
ApplicationListener
),使得它们能够监听Spring容器发布的事件。
- 注册应用程序中的事件监听器(如果有
-
完成容器的初始化:
- 发布
ContextRefreshedEvent
,通知所有监听器Spring容器已经完全启动。
- 发布
-
5. 获取Bean
- 当容器启动并完成初始化后,用户可以通过
ApplicationContext.getBean()
方法获取Bean的实例,使用已经准备好的Bean来处理业务逻辑。
6. 销毁与关闭容器
- 当应用程序结束或者容器关闭时,Spring会调用所有单例Bean的销毁方法,通常通过
close()
或destroy()
来关闭容器。 - 销毁过程包括:
- 调用所有实现了
DisposableBean
接口的Bean的destroy()
方法。 - 如果配置了自定义的销毁方法(如
destroy-method
),也会被执行。 - 发布
ContextClosedEvent
,通知监听器容器已经关闭。
- 调用所有实现了
Spring启动流程总结图:
+-------------------+
| 启动ApplicationContext |
+-------------------+
↓
+-------------------+
| 读取和解析配置文件 |
+-------------------+
↓
+-------------------+
| 注册BeanDefinition |
+-------------------+
↓
+-------------------+
| 容器刷新(refresh) |
+-------------------+
↓
| - 初始化环境变量 |
| - 初始化BeanFactory |
| - 执行BeanFactoryPostProcessor |
| - 注册BeanPostProcessor |
| - 实例化和初始化单例Bean |
| - 事件监听器注册 |
| - 发布ContextRefreshedEvent |
+-------------------+
↓
+-------------------+
| 获取Bean并使用 |
+-------------------+
↓
+-------------------+
| 容器销毁与关闭 |
+-------------------+
主要方法:
refresh()
:Spring容器的核心方法,负责完成Bean的创建、初始化、后处理等工作。getBean()
:从Spring容器中获取Bean实例的主要接口。close()
:关闭Spring容器,销毁Bean并清理资源。
总结:
Spring的启动流程围绕着容器的初始化和Bean的创建展开,通过读取配置文件、注册Bean定义、调用生命周期回调方法(如BeanPostProcessor
和BeanFactoryPostProcessor
)、初始化Bean及事件驱动等多个步骤,最终构建出一个完整的应用上下文。