Bean生命周期
Bean生命周期概述
Spring Bean的生命周期是指从Bean实例化到销毁的整个过程。理解Bean的生命周期对于正确使用Spring容器至关重要。
生命周期流程图
1. 实例化 (Instantiation)
↓
2. 属性赋值 (Populate Properties)
↓
3. BeanNameAware.setBeanName()
↓
4. BeanFactoryAware.setBeanFactory()
↓
5. ApplicationContextAware.setApplicationContext()
↓
6. BeanPostProcessor.postProcessBeforeInitialization()
↓
7. @PostConstruct
↓
8. InitializingBean.afterPropertiesSet()
↓
9. init-method
↓
10. BeanPostProcessor.postProcessAfterInitialization()
↓
Bean就绪,可以使用
↓
11. @PreDestroy
↓
12. DisposableBean.destroy()
↓
13. destroy-method生命周期详解
1. 实例化阶段
Spring容器通过反射创建Bean实例。
java
@Component
public class UserService {
public UserService() {
System.out.println("1. UserService构造器执行");
}
}2. 属性赋值
Spring容器为Bean注入依赖。
java
@Component
public class UserService {
@Autowired
private UserRepository userRepository;
// 构造器执行后,userRepository会被注入
}3. Aware接口回调
Spring提供了多个Aware接口,让Bean能够感知容器的存在。
java
@Component
public class UserService implements BeanNameAware,
BeanFactoryAware,
ApplicationContextAware {
@Override
public void setBeanName(String name) {
System.out.println("3. BeanNameAware: " + name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
System.out.println("4. BeanFactoryAware");
}
@Override
public void setApplicationContext(ApplicationContext context) {
System.out.println("5. ApplicationContextAware");
}
}4. BeanPostProcessor前置处理
在Bean初始化前执行。
java
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("6. BeanPostProcessor前置处理: " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("10. BeanPostProcessor后置处理: " + beanName);
return bean;
}
}5. @PostConstruct注解
JSR-250规范定义的初始化方法。
java
@Component
public class UserService {
@PostConstruct
public void init() {
System.out.println("7. @PostConstruct执行");
}
}6. InitializingBean接口
Spring提供的初始化接口。
java
@Component
public class UserService implements InitializingBean {
@Override
public void afterPropertiesSet() {
System.out.println("8. InitializingBean.afterPropertiesSet()");
}
}7. 自定义初始化方法
通过@Bean注解的initMethod属性或XML配置指定。
java
@Configuration
public class AppConfig {
@Bean(initMethod = "customInit")
public UserService userService() {
return new UserService();
}
}
public class UserService {
public void customInit() {
System.out.println("9. 自定义init-method执行");
}
}8. @PreDestroy注解
JSR-250规范定义的销毁方法。
java
@Component
public class UserService {
@PreDestroy
public void cleanup() {
System.out.println("11. @PreDestroy执行");
}
}9. DisposableBean接口
Spring提供的销毁接口。
java
@Component
public class UserService implements DisposableBean {
@Override
public void destroy() {
System.out.println("12. DisposableBean.destroy()");
}
}10. 自定义销毁方法
通过@Bean注解的destroyMethod属性或XML配置指定。
java
@Configuration
public class AppConfig {
@Bean(destroyMethod = "customDestroy")
public UserService userService() {
return new UserService();
}
}
public class UserService {
public void customDestroy() {
System.out.println("13. 自定义destroy-method执行");
}
}完整示例
java
@Component
public class LifecycleBean implements BeanNameAware,
BeanFactoryAware,
ApplicationContextAware,
InitializingBean,
DisposableBean {
private String beanName;
// 1. 构造器
public LifecycleBean() {
System.out.println("1. 构造器执行");
}
// 2. 属性注入
@Autowired
private ApplicationContext applicationContext;
// 3. BeanNameAware
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("3. BeanNameAware.setBeanName: " + name);
}
// 4. BeanFactoryAware
@Override
public void setBeanFactory(BeanFactory beanFactory) {
System.out.println("4. BeanFactoryAware.setBeanFactory");
}
// 5. ApplicationContextAware
@Override
public void setApplicationContext(ApplicationContext context) {
System.out.println("5. ApplicationContextAware.setApplicationContext");
}
// 7. @PostConstruct
@PostConstruct
public void postConstruct() {
System.out.println("7. @PostConstruct执行");
}
// 8. InitializingBean
@Override
public void afterPropertiesSet() {
System.out.println("8. InitializingBean.afterPropertiesSet");
}
// 9. 自定义初始化方法
public void customInit() {
System.out.println("9. 自定义初始化方法执行");
}
// 11. @PreDestroy
@PreDestroy
public void preDestroy() {
System.out.println("11. @PreDestroy执行");
}
// 12. DisposableBean
@Override
public void destroy() {
System.out.println("12. DisposableBean.destroy");
}
// 13. 自定义销毁方法
public void customDestroy() {
System.out.println("13. 自定义销毁方法执行");
}
}配置类:
java
@Configuration
public class AppConfig {
@Bean(initMethod = "customInit", destroyMethod = "customDestroy")
public LifecycleBean lifecycleBean() {
return new LifecycleBean();
}
}Bean作用域对生命周期的影响
Singleton(单例)
默认作用域,整个应用只有一个实例。
java
@Component
@Scope("singleton") // 默认值
public class SingletonBean {
// Bean在容器启动时创建
// Bean在容器关闭时销毁
}Prototype(原型)
每次请求都创建新实例。
java
@Component
@Scope("prototype")
public class PrototypeBean {
// 每次getBean()时创建新实例
// Spring不管理prototype bean的销毁
// 销毁回调不会被调用
}Request(请求)
Web环境中,每个HTTP请求创建一个实例。
java
@Component
@Scope("request")
public class RequestBean {
// 请求开始时创建
// 请求结束时销毁
}Session(会话)
Web环境中,每个HTTP Session创建一个实例。
java
@Component
@Scope("session")
public class SessionBean {
// 会话创建时创建
// 会话结束时销毁
}实用场景
1. 资源初始化
java
@Component
public class DatabaseConnectionPool {
private HikariDataSource dataSource;
@PostConstruct
public void init() {
dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("password");
System.out.println("数据库连接池初始化完成");
}
@PreDestroy
public void cleanup() {
if (dataSource != null) {
dataSource.close();
System.out.println("数据库连接池已关闭");
}
}
}2. 缓存预热
java
@Component
public class CacheWarmer {
@Autowired
private ProductService productService;
@Autowired
private CacheManager cacheManager;
@PostConstruct
public void warmUpCache() {
System.out.println("开始缓存预热...");
List<Product> hotProducts = productService.getHotProducts();
Cache cache = cacheManager.getCache("products");
for (Product product : hotProducts) {
cache.put(product.getId(), product);
}
System.out.println("缓存预热完成");
}
}3. 定时任务启动
java
@Component
public class ScheduledTaskManager {
@Autowired
private TaskScheduler taskScheduler;
private ScheduledFuture<?> scheduledTask;
@PostConstruct
public void startScheduledTask() {
scheduledTask = taskScheduler.scheduleAtFixedRate(
() -> System.out.println("执行定时任务"),
Duration.ofMinutes(5)
);
System.out.println("定时任务已启动");
}
@PreDestroy
public void stopScheduledTask() {
if (scheduledTask != null) {
scheduledTask.cancel(true);
System.out.println("定时任务已停止");
}
}
}最佳实践
推荐使用@PostConstruct和@PreDestroy
- 标准JSR-250规范
- 代码清晰,易于理解
- 不依赖Spring接口
避免在构造器中执行复杂逻辑
- 依赖可能未完全注入
- 使用@PostConstruct替代
注意Prototype作用域的销毁
- Spring不负责销毁
- 需要手动管理资源
合理使用BeanPostProcessor
- 用于通用的Bean处理逻辑
- 如AOP、缓存、事务等
初始化方法的执行顺序
@PostConstruct → InitializingBean → init-method销毁方法的执行顺序
@PreDestroy → DisposableBean → destroy-method
总结
理解Spring Bean的生命周期对于:
- 正确初始化资源
- 及时释放资源
- 实现自定义扩展
- 排查问题和调试
都非常重要。合理使用生命周期回调可以让我们的应用更加健壮和高效。