Skip to content

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("定时任务已停止");
        }
    }
}

最佳实践

  1. 推荐使用@PostConstruct和@PreDestroy

    • 标准JSR-250规范
    • 代码清晰,易于理解
    • 不依赖Spring接口
  2. 避免在构造器中执行复杂逻辑

    • 依赖可能未完全注入
    • 使用@PostConstruct替代
  3. 注意Prototype作用域的销毁

    • Spring不负责销毁
    • 需要手动管理资源
  4. 合理使用BeanPostProcessor

    • 用于通用的Bean处理逻辑
    • 如AOP、缓存、事务等
  5. 初始化方法的执行顺序

    @PostConstruct → InitializingBean → init-method
  6. 销毁方法的执行顺序

    @PreDestroy → DisposableBean → destroy-method

总结

理解Spring Bean的生命周期对于:

  • 正确初始化资源
  • 及时释放资源
  • 实现自定义扩展
  • 排查问题和调试

都非常重要。合理使用生命周期回调可以让我们的应用更加健壮和高效。