Spring 生命周期详解:从初识到精通
了解 Spring 生命周期对于我们更好地运用它非常重要。本篇文章力图用易懂、有趣的方式带你深入剖析 Spring 生命周期,让你成为 Spring 开发的专家。
目录
一、Spring 生命周期简介
要了解 Spring生命周期,我们需要分别了解 Spring 程序启动过程以及 Spring Bean的生命周期。下面开始详细介绍。
1.1 Spring 程序启动过程
Spring 程序启动主要分为这几个步骤:
- 创建 ApplicationContext 对象
- 读取配置文件进行解析
- 初始化 BeanDefinition
- 创建单例池(Singleton Bean)
1.2 Spring Bean 的生命周期
Spring Bean 生命周期可分为以下阶段:
- BeanDefinition 到 Bean 实例
- Bean 实例化(Instantiation)
- 依赖注入(Dependency Injection)
- 初始化回调与资源销毁
二、BeanFactory 和 ApplicationContext
2.1 了解 BeanFactory
BeanFactory 是 Spring 中最核心的接口,主要提供了以下功能:
- 根据 BeanDefinition 创建 Bean 实例
- 依赖解析与注入
- 为 Bean 提供生命周期管理
2.2 深入 ApplicationContext
ApplicationContext 是 BeanFactory 的实现类,扩充了一些功能,如:
- 事件发布与订阅
- 国际化支持
- 资源访问
- 与 Java EE 之间的集成
三、Spring Bean 生命周期详解
3.1 BeanDefinition 到 Bean 实例
BeanDefinition 是 Bean 配置的原材料,包括了Bean 实例的各种属性和依赖关系等信息。BeanFactory 根据 BeanDefinition 来创建、注入和实例化 Bean。
- 读取和解析配置信息:将配置文件(如 XML 文件、Java Config)转化为 BeanDefinition 对象
- 注册到 BeanDefinitionRegistry:BeanDefinition 对象被注册到 BeanFactory 的 BeanDefinitionRegistry 中进行管理
3.2 Bean 实例化过程
Bean 实例化分为以下几个步骤:
- 选择构造器:选择合适的构造器进行实例化
- 实例创建:使用反射技术创建 Bean 实例
- 属性设置:根据 BeanDefinition 中的属性信息为 Bean 实例设置属性(赋值)
3.3 依赖注入
依赖注入可以分为以下几个步骤:
- 解析依赖关系:从 BeanDefinition 中获取到所有依赖的 Bean 名称
- 获取依赖的 Bean 实例:根据名称从 BeanFactory 中获取依赖的 Bean 实例
- 对目标 Bean 依赖注入:将依赖的 Bean 实例注入到目标 Bean 中
3.4 初始化回调与资源销毁
在 Bean 实例化后,Spring 提供了回调方法的支持来执行一些特定的操作。
- 初始化回调:可以通过实现 InitializingBean 接口的
afterPropertiesSet
方法或定义@PostConstruct
注解的方法来执行初始化操作 - 资源销毁:可以通过实现 DisposableBean 接口的
destroy
方法或定义@PreDestroy
注解的方法来执行销毁操作
四、重要的 Bean 生命周期接口
4.1 BeanPostProcessor
BeanPostProcessor 接口允许在 Bean 初始化的过程中执行自定义操作。它提供了两个方法:
- postProcessBeforeInitialization:在 Bean 初始化前调用,例如在调用 InitializingBean 的
afterPropertiesSet
方法之前 - postProcessAfterInitialization:在 Bean 初始化后调用,例如在调用
@PostConstruct
注解的方法之后
实现此接口,你可以在 Bean 的生命周期中,通过实现类插入定制的动作。
4.2 InstantiationAwareBeanPostProcessor
InstantiationAwareBean_postProcessor 接口继承自 BeanPostProcessor,提供在 Bean 实例化之前进行扩展操作的能力。
- postProcessBeforeInstantiation:在实例化 Bean 之前调用,例如在选择合适的构造器之前
- postProcessAfterInstantiation:在实例化 Bean 之后调用,例如在属性设置之前
4.3 SmartInstantiationAwareBeanPostProcessor
SmartInstantiationAwareBeanPostProcessor 继承自 InstantiationAwareBeanPostProcessor,提供对简单类型字段的候选者的选择。
- determineCandidateConstructors:提供了自定义选择构造器的能力
- getEarlyBeanReference:有助于解决循环依赖问题
五、实践案例
假设我们有一个简单的 Spring 应用,目标是了解 Bean 生命周期的各个阶段。
5.1 创建简单的 Spring 应用
以下是一个简单的 Spring 配置和示例 Bean:
@Configuration
public class AppConfig {
@Bean
public UserService userService() {
return new UserService```java
new UserService();
}
}
@Component
public class UserService {
@Autowired
private OrderService orderService;
public UserService() {
System.out.println("UserService: 构造方法");
}
@PostConstruct
public void init() {
System.out.println("UserService: 初始化");
}
@PreDestroy
public void destroy() {
System.out.println("UserService: 销毁");
}
}
@Component
public class OrderService {
public OrderService() {
System.out.println("OrderService: 构造方法");
}
}
上面的代码定义了一个简单的 Spring 配置类 AppConfig
,其中包含一个 userService
Bean。UserService 有一个对 OrderService 的依赖。这两个 Bean 包含了一些生命周期相关的方法(构造方法、初始化和销毁)。
5.2 分析 Bean 生命周期
现在我们来分析整个 Bean 生命周期,看看在不同阶段输出的内容。启动 Spring 应用,将看到如下输出:
OrderService: 构造方法
UserService: 构造方法
UserService: 初始化
首先,OrderService 的构造方法被调用,接着是 UserService 的构造方法。最后,UserService 的初始化方法被调用。接下来,我们以 UserService 为例,看看在生命周期的各个阶段都发生了什么:
- 读取和解析配置信息:Spring 从配置类中读取配置信息,并解析为 BeanDefinition 对象
- 注册到 BeanDefinitionRegistry:BeanDefinition 对象被注册到 BeanFactory 中
- 选择合适的构造器:Spring 根据提供的构造方法和依赖关系,查找并选择合适的构造器来实例化 Bean
- 实例化 Bean:通过构造器实例化 Bean,在这里 UserService 和 OrderService 的构造方法被调用
- 设置 Bean 属性:Spring 根据配置信息设置 Bean 的属性,这里 UserService 的 OrderService 属性被自动装配
- 初始化 Bean:执行初始化方法,这里 UserService 的 init 方法被调用(@PostConstruct 注解标记的)
- Bean 放入容器:实例化好的 Bean 被放入 Spring IoC 容器并被管理
- 销毁 Bean:应用停止时,执行销毁方法(@PreDestroy 注解标记的)
从上述分析中,我们可以看到 Bean 生命周期的多个阶段,并了解 Spring 如何实例化、装配和管理 Bean。为了更深入了解 Bean 生命周期,我们可以通过在 UserService 中实现 InitializingBean 和 DisposableBean 接口,并重写接口方法来观察输出结果。
@Component
public class UserService implements InitializingBean, DisposableBean {
// ...其他代码
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("UserService: afterPropertiesSet");
}
@Override
public void destroy() throws Exception {
System.out.println("UserService: DisposableBean 销毁方法");
}
}
再次运行应用,我们将看到如下输出:
OrderService: 构造方法
UserService: 构造方法
UserService: 初始化
UserService: afterPropertiesSet
这次,除了 @PostConstruct
注解的方法,UserService 初始化阶段还包括调用 afterPropertiesSet
方法。
六、总结
在本文中,我们首先介绍了 Spring Bean 的生命周期,并学习了 Bean 生命周期中的各个阶段。