Java面试题 - 说下 Spring Bean的生命周期?
一、引言
Spring框架作为Java企业级开发的事实标准,其核心特性之一就是IoC(控制反转)容器,而Bean则是Spring IoC容器管理的基本单元。理解Spring Bean的生命周期对于掌握Spring框架至关重要,它不仅有助于我们更好地使用Spring,还能在遇到问题时快速定位和解决。
二、Bean生命周期概述
Spring Bean的生命周期指的是一个Bean从创建到销毁的整个过程。在这个过程中,Spring容器提供了多个扩展点,允许开发者在Bean的不同生命周期阶段插入自定义逻辑。
以下是Bean生命周期的核心阶段:
三、详细生命周期阶段
1. 实例化Bean
Spring容器首先会通过构造函数或工厂方法创建Bean的实例。此时Bean的属性还未被设置,处于"原始"状态。
// 通过构造函数实例化
<bean id="exampleBean" class="com.example.ExampleBean"/>
2. 属性赋值(依赖注入)
容器根据配置为Bean设置属性值和其他Bean的引用(依赖注入)。
public class ExampleBean {
private AnotherBean anotherBean;
// Setter方法用于依赖注入
public void setAnotherBean(AnotherBean anotherBean) {
this.anotherBean = anotherBean;
}
}
3. Aware接口回调
如果Bean实现了各种Aware接口,Spring会调用相应的方法:
- BeanNameAware:设置Bean的名称
- BeanFactoryAware:设置BeanFactory
- ApplicationContextAware:设置ApplicationContext(在BeanFactoryAware之后)
public class AwareBean implements BeanNameAware, BeanFactoryAware {
private String beanName;
private BeanFactory beanFactory;
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
}
4. BeanPostProcessor前置处理
所有实现了BeanPostProcessor
接口的类会在每个Bean初始化前后执行自定义逻辑。
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("Before初始化: " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("After初始化: " + beanName);
return bean;
}
}
5. 初始化阶段
Bean的初始化包括以下步骤:
- InitializingBean.afterPropertiesSet():如果Bean实现了该接口
- 自定义init方法:通过
init-method
属性或@PostConstruct
注解指定
public class InitBean implements InitializingBean {
@Override
public void afterPropertiesSet() {
System.out.println("InitializingBean的afterPropertiesSet()");
}
@PostConstruct
public void customInit() {
System.out.println("@PostConstruct自定义初始化方法");
}
public void xmlInit() {
System.out.println("XML配置的init-method");
}
}
XML配置示例:
<bean id="initBean" class="com.example.InitBean" init-method="xmlInit"/>
6. BeanPostProcessor后置处理
初始化完成后,BeanPostProcessor
的postProcessAfterInitialization
方法会被调用。
7. Bean就绪可用
此时Bean已经完全初始化,可以被应用程序使用。
8. 销毁阶段
当容器关闭时,Bean进入销毁阶段:
- @PreDestroy注解方法
- DisposableBean.destroy():如果Bean实现了该接口
- 自定义destroy方法:通过
destroy-method
属性指定
public class DestroyBean implements DisposableBean {
@PreDestroy
public void preDestroy() {
System.out.println("@PreDestroy方法");
}
@Override
public void destroy() {
System.out.println("DisposableBean的destroy()");
}
public void customDestroy() {
System.out.println("XML配置的destroy-method");
}
}
XML配置示例:
<bean id="destroyBean" class="com.example.DestroyBean" destroy-method="customDestroy"/>
四、完整的生命周期流程图
开始
│
▼
[实例化Bean](调用构造函数创建对象)
│
▼
[属性赋值/依赖注入](填充@Autowired/@Value等属性)
│
▼
[Aware接口回调](执行BeanNameAware/BeanFactoryAware等接口方法)
│
▼
[BeanPostProcessor前置处理](postProcessBeforeInitialization())
│
▼
[InitializingBean.afterPropertiesSet](接口定义的初始化逻辑)
│
▼
[自定义init方法](执行@Bean(initMethod)或XML指定的init-method)
│
▼
[BeanPostProcessor后置处理](postProcessAfterInitialization())
│
▼
[Bean就绪可用](进入运行时状态)
│
▼
[容器关闭](Context.close()触发销毁流程)
│
▼
[@PreDestroy方法](执行标注@PreDestroy的方法)
│
▼
[DisposableBean.destroy](接口定义的销毁逻辑)
│
▼
[自定义destroy方法](执行@Bean(destroyMethod)或XML指定的destroy-method)
│
▼
结束
五、生命周期扩展点总结
扩展点 | 说明 | 实现方式 |
---|---|---|
BeanPostProcessor | 在Bean初始化前后执行逻辑 | 实现接口并注册为Bean |
InitializingBean | 属性设置完成后执行初始化 | 实现接口 |
DisposableBean | Bean销毁时执行清理 | 实现接口 |
@PostConstruct | 初始化方法 | 注解 |
@PreDestroy | 销毁方法 | 注解 |
init-method | 自定义初始化方法 | XML配置或@Bean注解 |
destroy-method | 自定义销毁方法 | XML配置或@Bean注解 |
六、实际应用场景
- 资源初始化:数据库连接、线程池等在初始化阶段创建
- 缓存预热:在Bean就绪后加载缓存数据
- 资源清理:在销毁阶段关闭文件句柄、释放连接等
- 性能监控:通过BeanPostProcessor实现AOP监控
七、总结
Spring Bean的生命周期是Spring框架的核心概念之一,理解它对于开发高质量的Spring应用程序至关重要。通过合理利用生命周期中的各个扩展点,我们可以实现更灵活、更强大的功能。记住,BeanPostProcessor是最强大的扩展点,它可以在容器中所有Bean的创建过程中插入自定义逻辑。
掌握Bean生命周期不仅有助于日常开发,也是应对复杂Spring面试问题的关键。建议读者通过实际编码练习来加深对各个阶段的理解。