Bean 生命周期
Spring Bean 从被容器创建到最终销毁,经历一套固定的生命周期阶段。理解这些阶段有助于正确使用初始化/销毁回调,以及排查 Bean 状态异常问题。
生命周期全流程
1. 实例化(Instantiation)
└── 调用构造器,创建 Bean 实例
2. 属性注入(Property Population)
└── 填充 @Autowired、@Value 等依赖
3. Aware 接口回调
├── BeanNameAware.setBeanName()
├── BeanClassLoaderAware.setBeanClassLoader()
├── BeanFactoryAware.setBeanFactory()
├── EnvironmentAware.setEnvironment()
├── ApplicationContextAware.setApplicationContext()
└── (其他 Aware 接口...)
4. BeanPostProcessor#postProcessBeforeInitialization()
└── AOP 代理、@Validated 增强等在此介入
5. 初始化(Initialization)
├── @PostConstruct 标注的方法
├── InitializingBean.afterPropertiesSet()
└── @Bean(initMethod = "...") 指定的方法
6. BeanPostProcessor#postProcessAfterInitialization()
└── AOP 代理对象在此生成(替换原始 Bean)
7. Bean 就绪,放入容器(singletonObjects)
↓ 应用运行 ↓
8. 销毁(Destruction)
├── @PreDestroy 标注的方法
├── DisposableBean.destroy()
└── @Bean(destroyMethod = "...") 指定的方法
销毁回调仅对单例(Singleton) Bean 生效;原型(Prototype)Bean 由容器创建后即交出管理,不会触发销毁方法。
一、实例化
Spring 优先使用无参构造器,若只有有参构造器则自动注入参数:
@Service
public class OrderService {
private final OrderRepository repo;
private final MailService mailService;
// 单构造器:Spring 自动注入,无需 @Autowired
public OrderService(OrderRepository repo, MailService mailService) {
this.repo = repo;
this.mailService = mailService;
// 注意:此时 @Autowired 字段尚未注入,不能在构造器中使用字段注入的依赖
}
}依赖注入方式详见 IOC与DI。
二、Aware 接口
实现 Aware 接口让 Bean 获取容器内部信息,但会造成与 Spring 的强耦合,非必要不使用:
@Component
public class SpringContextHolder
implements ApplicationContextAware, BeanNameAware, EnvironmentAware {
private static ApplicationContext context;
private String beanName;
private Environment environment;
// 3-a:BeanNameAware — 获取当前 Bean 在容器中的名称
@Override
public void setBeanName(String name) {
this.beanName = name;
// 此时属性注入已完成,可以安全使用字段
}
// 3-b:ApplicationContextAware — 获取整个 ApplicationContext
@Override
public void setApplicationContext(ApplicationContext ctx) {
context = ctx;
}
// 3-c:EnvironmentAware — 获取 Environment(读取配置属性)
@Override
public void setEnvironment(Environment env) {
this.environment = env;
}
// 静态工具方法:在非 Spring 管理的类中手动获取 Bean
public static <T> T getBean(Class<T> clazz) {
return context.getBean(clazz);
}
public static String getProperty(String key) {
return context.getBean(Environment.class).getProperty(key);
}
}常用 Aware 接口:
| 接口 | 注入内容 | 典型用途 |
|---|---|---|
BeanNameAware | 当前 Bean 的注册名 | 日志、区分同类型多实例 |
BeanFactoryAware | BeanFactory 实例 | 编程式获取 Bean |
ApplicationContextAware | ApplicationContext 实例 | 静态工具类获取 Bean |
EnvironmentAware | Environment 实例 | 读取配置属性 |
ResourceLoaderAware | ResourceLoader 实例 | 加载类路径资源 |
MessageSourceAware | MessageSource 实例 | 国际化消息 |
ApplicationEventPublisherAware | ApplicationEventPublisher | 发布事件(也可直接注入) |
三、BeanPostProcessor
BeanPostProcessor 是 Spring 最强大的扩展点,对容器中所有 Bean 生效:
@Component
@Slf4j
public class TimingBeanPostProcessor implements BeanPostProcessor {
// 初始化前(@PostConstruct 执行之前)
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
log.debug("Before init: {}", beanName);
return bean; // 必须返回 bean(或替换后的对象)
}
// 初始化后(AOP 代理在此生成)
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
log.debug("After init: {}", beanName);
// 可以在这里包装 Bean,返回代理对象
return bean;
}
}Spring 内部大量使用 BeanPostProcessor:
| BeanPostProcessor | 作用 |
|---|---|
AutowiredAnnotationBeanPostProcessor | 处理 @Autowired、@Value |
CommonAnnotationBeanPostProcessor | 处理 @PostConstruct、@PreDestroy、@Resource |
AnnotationAwareAspectJAutoProxyCreator | 生成 AOP 代理对象 |
PersistenceAnnotationBeanPostProcessor | 处理 JPA @PersistenceContext |
四、初始化方法
三种方式执行顺序固定:@PostConstruct → afterPropertiesSet() → initMethod
@Service
@Slf4j
public class CacheService implements InitializingBean {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private UserRepository userRepository;
// 方式一:@PostConstruct(推荐,JSR-250 标准,无 Spring 耦合)
@PostConstruct
public void warmUp() {
log.info("缓存预热开始...");
// 此时所有依赖已注入,可以安全使用
List<User> hotUsers = userRepository.findTopActive(100);
hotUsers.forEach(u -> redisTemplate.opsForValue().set("user:" + u.getId(), u));
log.info("缓存预热完成,共加载 {} 个用户", hotUsers.size());
}
// 方式二:InitializingBean(Spring 接口,有耦合,不推荐)
@Override
public void afterPropertiesSet() {
log.info("afterPropertiesSet 执行");
}
}
// 方式三:@Bean(initMethod = "...")(适合第三方类,无法修改源码时)
@Configuration
public class ThirdPartyConfig {
@Bean(initMethod = "init", destroyMethod = "close")
public HeavyResource heavyResource() {
return new HeavyResource(); // HeavyResource.init() 在 Bean 就绪后调用
}
}@PostConstruct 的典型用途
@Component
public class ApplicationStartupRunner {
@Autowired
private DataSource dataSource;
@PostConstruct
public void validateDatabase() {
// 依赖注入完成后立即验证数据库连通性
try (Connection conn = dataSource.getConnection()) {
log.info("数据库连接验证通过: {}", conn.getMetaData().getURL());
} catch (SQLException e) {
throw new IllegalStateException("数据库连接失败,应用启动中止", e);
}
}
}五、销毁方法
三种方式执行顺序:@PreDestroy → destroy() → destroyMethod
@Service
@Slf4j
public class ResourceService implements DisposableBean {
private ScheduledExecutorService scheduler;
private HttpClient httpClient;
@PostConstruct
public void init() {
scheduler = Executors.newScheduledThreadPool(4);
httpClient = HttpClient.newHttpClient();
}
// 方式一:@PreDestroy(推荐)
@PreDestroy
public void cleanup() {
log.info("关闭 HTTP 客户端...");
httpClient = null;
}
// 方式二:DisposableBean(不推荐,有 Spring 耦合)
@Override
public void destroy() throws Exception {
log.info("关闭调度器...");
scheduler.shutdown();
if (!scheduler.awaitTermination(10, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
}
}
}原型(Prototype)Bean:Spring 创建后即交出控制权,不调用
@PreDestroy和destroy()。若需清理,需手动实现或使用@Bean(destroyMethod = "")阻止自动推断(防止调用close()/shutdown()等公开方法)。
六、SmartLifecycle — 容器级别生命周期
SmartLifecycle 控制 Bean 随 Spring 容器启动/停止的行为,与 Bean 初始化回调不同:Bean 初始化回调在 Bean 就绪时触发,而 SmartLifecycle 在整个容器启动/关闭时触发。
@Component
@Slf4j
public class MessageConsumer implements SmartLifecycle {
private volatile boolean running = false;
private final ScheduledExecutorService poller =
Executors.newSingleThreadScheduledExecutor();
// 容器启动完成后调用(所有 Bean 就绪之后)
@Override
public void start() {
log.info("消息消费者启动...");
poller.scheduleAtFixedRate(this::poll, 0, 1, TimeUnit.SECONDS);
running = true;
}
// 容器关闭时调用(异步,调用 callback.run() 通知 Spring 关闭完成)
@Override
public void stop(Runnable callback) {
log.info("消息消费者停止...");
poller.shutdown();
running = false;
callback.run(); // 必须调用,否则 Spring 会等待超时
}
@Override
public boolean isRunning() {
return running;
}
// phase 值越小越早启动、越晚停止;越大越晚启动、越早停止
// 默认 Integer.MAX_VALUE / 2
@Override
public int getPhase() {
return 100; // 优先于默认值更早启动
}
// 是否在容器 refresh 后自动启动(默认 false)
@Override
public boolean isAutoStartup() {
return true;
}
private void poll() {
// 拉取消息处理逻辑
}
}七、完整执行顺序验证
@Component
@Slf4j
public class LifecycleDemoBean
implements BeanNameAware, ApplicationContextAware,
InitializingBean, DisposableBean {
// 1. 构造器
public LifecycleDemoBean() {
log.info("① 构造器");
}
// 2. 属性注入(@Autowired)— 由 AutowiredAnnotationBeanPostProcessor 处理
// 3. Aware 接口
@Override
public void setBeanName(String name) {
log.info("③ setBeanName: {}", name);
}
@Override
public void setApplicationContext(ApplicationContext ctx) {
log.info("③ setApplicationContext");
}
// 4. BeanPostProcessor#before(框架内部,日志见 TimingBeanPostProcessor)
// 5a. @PostConstruct
@PostConstruct
public void postConstruct() {
log.info("⑤ @PostConstruct");
}
// 5b. InitializingBean
@Override
public void afterPropertiesSet() {
log.info("⑤ afterPropertiesSet");
}
// 6. BeanPostProcessor#after(AOP 代理在此生成)
// 8a. @PreDestroy
@PreDestroy
public void preDestroy() {
log.info("⑧ @PreDestroy");
}
// 8b. DisposableBean
@Override
public void destroy() {
log.info("⑧ DisposableBean.destroy()");
}
}输出顺序:
① 构造器
③ setBeanName: lifecycleDemoBean
③ setApplicationContext
⑤ @PostConstruct
⑤ afterPropertiesSet
(应用运行...)
⑧ @PreDestroy
⑧ DisposableBean.destroy()
常见误区
| 误区 | 正确理解 |
|---|---|
在构造器中使用 @Autowired 字段 | 构造器执行时属性注入尚未完成;改用构造器注入 |
Prototype Bean 期望 @PreDestroy 执行 | Spring 不管理 Prototype 的销毁,需手动清理 |
@PostConstruct 中启动异步任务 | 容器未完全就绪;改用 SmartLifecycle.start() 或 ApplicationReadyEvent |
BeanPostProcessor 依赖普通 Bean | BeanPostProcessor 过早实例化,其依赖可能无法被 AOP 代理 |