在 Spring 框架中,Bean 的生命周期管理是其核心功能之一。理解 Bean 的生命周期,对于开发者精准控制 Bean 的行为、优化资源管理以及排查问题至关重要。本文将深入剖析 Spring Bean 从创建到销毁的完整流程,结合代码示例和实际应用场景,带你掌握生命周期的关键节点与扩展技巧。
一、Bean 生命周期总览
Spring Bean 的生命周期可概括为 “创建 - 初始化 - 使用 - 销毁” 四大阶段,涉及多个扩展点(如接口回调、注解触发)。完整流程如下:
二、阶段详解与代码实践
1. 实例化(Instantiation)
作用:通过反射创建 Bean 的实例(调用构造方法)。
关键:此时仅完成对象创建,依赖注入和初始化尚未执行。
public class UserService {
public UserService() {
System.out.println("1. 实例化:调用构造方法");
}
}
2. 依赖注入(Dependency Injection)
作用:Spring 容器将 Bean 依赖的其他对象(如 UserDao
)注入到当前 Bean 中。
支持方式:构造器注入、Setter 注入、字段注入(@Autowired
)。
public class UserService {
@Autowired
private UserDao userDao; // 依赖注入
public UserService() {
System.out.println("1. 实例化:调用构造方法");
}
// Setter 注入示例(可选)
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
System.out.println("2. 依赖注入:通过 Setter 注入 UserDao");
}
}
3. Aware 接口回调(Optional)
Spring 提供 Aware
系列接口,让 Bean 主动获取容器信息(如 Bean 名称、应用上下文)。常见接口:
BeanNameAware
:获取 Bean 在容器中的名称BeanFactoryAware
:获取BeanFactory
容器ApplicationContextAware
:获取ApplicationContext
(更强大的容器上下文)
public class UserService implements BeanNameAware {
private String beanName;
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("3. Aware 回调:Bean 名称为 " + beanName);
}
}
4. BeanPostProcessor 前置处理
作用:全局拦截所有 Bean 的初始化流程,在初始化前修改 Bean 实例(如添加代理、修改属性)。
扩展点:实现 BeanPostProcessor
接口的 postProcessBeforeInitialization
方法。
@Component
public class LogBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("4. BeanPostProcessor 前置处理:" + beanName);
return bean; // 返回修改后的 Bean(或原实例)
}
}
5. 初始化阶段(Initialization)
初始化是 Bean 生命周期的核心扩展点,支持 三种方式(优先级:注解 > 接口 > XML 配置):
方式 1:@PostConstruct 注解(推荐)
作用:依赖注入完成后,自动触发标注方法(无需实现接口)
public class UserService {
@PostConstruct
public void initByAnnotation() {
System.out.println("5. 初始化:@PostConstruct 触发");
}
}
方式 2:InitializingBean 接口
作用:实现 afterPropertiesSet
方法,在依赖注入后执行初始化。
public class UserService implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("5. 初始化:InitializingBean 触发");
}
}
方式 3:XML 配置 init-method
作用:在 XML 中指定初始化方法,与注解 / 接口方式兼容。
<bean id="userService" class="com.example.UserService" init-method="initByXml"/>
public class UserService {
public void initByXml() {
System.out.println("5. 初始化:XML init-method 触发");
}
}
6. BeanPostProcessor 后置处理
作用:全局拦截 Bean 初始化流程,在初始化后修改 Bean(如 AOP 代理创建)。
@Component
public class AopBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("6. BeanPostProcessor 后置处理:" + beanName);
// 此处可返回代理对象(如通过 Proxy.newProxyInstance 创建)
return bean;
}
}
7. Bean 就绪与使用
经过以上流程,Bean 已完成初始化,进入 “就绪状态”,可通过 getBean()
获取,或被其他 Bean 依赖使用。
@SpringBootApplication
public class App {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(App.class);
UserService userService = context.getBean(UserService.class);
System.out.println("7. Bean 就绪:" + userService);
}
}
8. 销毁阶段(Destruction)
作用:容器关闭时,执行 Bean 的销毁逻辑(释放资源、关闭连接等)。支持 三种方式(优先级:注解 > 接口 > XML 配置):
方式 1:@PreDestroy 注解
public class UserService {
@PreDestroy
public void destroyByAnnotation() {
System.out.println("8. 销毁:@PreDestroy 触发");
}
}
方式 2:DisposableBean 接口
public class UserService implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("8. 销毁:DisposableBean 触发");
}
}
方式 3:XML 配置 destroy-method
<bean id="userService" class="com.example.UserService" destroy-method="destroyByXml"/>
public class UserService {
public void destroyByXml() {
System.out.println("8. 销毁:XML destroy-method 触发");
}
}
三、常见问题与解决方案
1. 初始化方法不执行?
- 检查是否开启注解支持:
@ComponentScan
或 XML 中配置<context:annotation-config/>
。 - 确保 Bean 被 Spring 容器管理(加
@Component
或 XML 配置)。
2. BeanPostProcessor 不生效?
- 确保实现类标注
@Component
或通过 XML 配置扫描。 BeanPostProcessor
是 全局生效 的,需注入到 Spring 容器中。
3. 原型 Bean 销毁方法不执行?
- 原型 Bean 需手动调用
destroyBean
触发销毁,Spring 不自动管理。
四、总结
Spring Bean 的生命周期通过 “实例化、依赖注入、初始化、销毁” 四大阶段,结合丰富的扩展点(注解、接口、BeanPostProcessor),实现了灵活的 Bean 管理。