Bean生命周期:从出生到入土的完整日记

123 阅读3分钟

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() // 核心方法