4.1 Bean生命周期:从出生到入土的完整日记
一、Bean的一生全景图
%% Mermaid时序图(可直接在Markdown渲染)
sequenceDiagram
participant 容器 as Spring容器
participant Bean as 你的Bean
participant BPP as BeanPostProcessor
participant Aware as Aware接口
容器->>Bean: 1. new实例化(出生证明)
容器->>Bean: 2. 属性注入(填户口本)
容器->>Bean: 3. Aware接口回调(办身份证)
BPP->>Bean: 4. postProcessBeforeInitialization(入学体检)
Bean-->>Bean: 5. @PostConstruct(新生军训)
Bean-->>Bean: 6. afterPropertiesSet(岗前培训)
Bean-->>Bean: 7. init-method(转正仪式)
BPP->>Bean: 8. postProcessAfterInitialization(颁发工牌)
Note over Bean: 正式工作阶段
容器->>Bean: 9. @PreDestroy(退休通知)
Bean-->>Bean: 10. destroy()(工作交接)
Bean-->>Bean: 11. destroy-method(领养老金)
二、生命周期的十二道金牌
代码:
@SpringBootApplication
public class BeanLifecycleDemo {
// 测试Bean实现所有关键接口
@Component
static class SuperBean implements BeanNameAware, ApplicationContextAware,
InitializingBean, DisposableBean {
public SuperBean() {
System.out.println("[1] 构造方法:new对象");
}
@Autowired
public void injectDependency(Object obj) {
System.out.println("[2] @Autowired注入:依赖注入完成");
}
@Override
public void setBeanName(String name) {
System.out.println("[3] BeanNameAware:我的名字是" + name);
}
@Override
public void setApplicationContext(ApplicationContext ctx) {
System.out.println("[4] ApplicationContextAware:拿到容器身份证");
}
@PostConstruct
public void postConstruct() {
System.out.println("[5] @PostConstruct:初始化前最后检查");
}
@Override
public void afterPropertiesSet() {
System.out.println("[6] InitializingBean:属性设置完毕");
}
public void customInit() {
System.out.println("[7] init-method:自定义初始化");
}
@PreDestroy
public void preDestroy() {
System.out.println("[8] @PreDestroy:准备退休");
}
@Override
public void destroy() {
System.out.println("[9] DisposableBean:销毁资源");
}
public void customDestroy() {
System.out.println("[10] destroy-method:清理战场");
}
}
// 配置类
@Configuration
public static class Config {
@Bean(initMethod = "customInit", destroyMethod = "customDestroy")
public SuperBean superBean() {
return new SuperBean();
}
@Bean
public static BeanPostProcessor tracker() {
return new BeanPostProcessor() {
@Override
public Object postProcessBeforeInitialization(Object bean, String name) {
if (bean instanceof SuperBean) {
System.out.println("[4.5] BeanPostProcessor前置处理");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String name) {
if (bean instanceof SuperBean) {
System.out.println("[7.5] BeanPostProcessor后置处理");
}
return bean;
}
};
}
}
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(BeanLifecycleDemo.class, args);
ctx.close(); // 触发销毁
}
}
控制台输出顺序:
[1] 构造方法:new对象
[2] @Autowired注入:依赖注入完成
[3] BeanNameAware:我的名字是superBean
[4] ApplicationContextAware:拿到容器身份证
[4.5] BeanPostProcessor前置处理
[5] @PostConstruct:初始化前最后检查
[6] InitializingBean:属性设置完毕
[7] init-method:自定义初始化
[7.5] BeanPostProcessor后置处理
...(运行阶段)
[8] @PreDestroy:准备退休
[9] DisposableBean:销毁资源
[10] destroy-method:清理战场
三、生命周期中的隐藏关卡(高级技巧)
1. Aware接口全家桶:
@Component
public class AwareBean implements
BeanFactoryAware, // 获取Bean工厂
ResourceLoaderAware, // 获取资源加载器
EnvironmentAware { // 获取环境变量
@Override
public void setBeanFactory(BeanFactory factory) {
System.out.println("拿到BeanFactory,可以手动创建Bean");
}
@Override
public void setResourceLoader(ResourceLoader loader) {
System.out.println("获取资源加载器,可读取classpath文件");
}
@Override
public void setEnvironment(Environment env) {
System.out.println("读取环境变量:" + env.getProperty("java.version"));
}
}
2. BeanPostProcessor黑魔法:
@Component
public class CustomProcessor implements BeanPostProcessor {
// 篡改Bean实例
@Override
public Object postProcessBeforeInitialization(Object bean, String name) {
if (bean instanceof OriginalBean) {
System.out.println("狸猫换太子:替换Bean实例");
return new ProxyBean();
}
return bean;
}
// 动态代理增强
@Override
public Object postProcessAfterInitialization(Object bean, String name) {
if (bean instanceof ServiceImpl) {
return Proxy.newProxyInstance(
bean.getClass().getClassLoader(),
bean.getClass().getInterfaces(),
(proxy, method, args) -> {
System.out.println("【代理增强】方法执行前日志");
return method.invoke(bean, args);
}
);
}
return bean;
}
}
3. 生命周期扩展实战:
// 实现SmartLifecycle控制启动顺序
@Component
public class DatabaseInitializer implements SmartLifecycle {
private boolean isRunning = false;
@Override
public void start() {
System.out.println("系统启动时优先执行数据库初始化");
isRunning = true;
}
@Override
public void stop() {
System.out.println("系统关闭时最后释放数据库连接");
isRunning = false;
}
@Override
public boolean isRunning() {
return isRunning;
}
@Override
public int getPhase() {
return Integer.MIN_VALUE; // 最高优先级
}
}
四、常见翻车现场(避坑指南)
案例1:构造方法中调用@PostConstruct
@Component
public class CrashBean {
public CrashBean() {
postConstruct(); // 错误!此时依赖注入未完成
}
@PostConstruct
public void postConstruct() {
System.out.println("这里可能NPE");
}
}
案例2:循环依赖导致生命周期中断
@Component
public class BeanA {
@Autowired
private BeanB b;
@PostConstruct
public void init() {
System.out.println("永远执行不到这里");
}
}
@Component
public class BeanB {
@Autowired
private BeanA a;
}
案例3:prototype Bean的销毁方法不执行
@Configuration
public class PrototypeConfig {
@Bean
@Scope("prototype")
public DisposableBean prototypeBean() {
return new DisposableBean() {
@Override
public void destroy() {
System.out.println("永远不会执行!");
}
};
}
}
五、面试核武器(高频考点)
1. 生命周期顺序题
Q:说说Bean从创建到销毁的完整过程?
A:参考以下口诀:
一构二注三 Aware,
四前处理五 Construct,
六 Initializing,七 init,
八后处理才完成。
销毁先 PreDestroy,
九 Disposable,十 destroy。
2. 设计模式题
Q:Bean生命周期中用了哪些设计模式?
A:
- 模板方法模式:AbstractApplicationContext.refresh()
- 观察者模式:ContextRefreshedEvent事件发布
- 代理模式:BeanPostProcessor生成代理对象
3. 源码追踪题
Q:Spring是如何保证初始化顺序的?
A:关键源码路径:
AbstractApplicationContext.refresh()
→ finishBeanFactoryInitialization()
→ DefaultListableBeanFactory.preInstantiateSingletons()
→ AbstractBeanFactory.getBean()
→ doCreateBean() // 核心方法