Spring Bean 的生命周期详解

        Spring Bean 的生命周期是指从 Bean 的创建、初始化到销毁的完整过程,Spring 提供了多个扩展点允许开发者介入这一过程。以下是 Bean 生命周期的完整流程和关键扩展点:

1. Bean 生命周期的核心阶段

Spring Bean 的生命周期可以分为以下几个主要阶段:

(1) Bean 的实例化(Instantiation)

  • 触发条件:当容器启动或首次请求 Bean 时,Spring 通过反射或工厂方法创建Bean 实例。

  • 底层机制

    • 如果 Bean 是单例(Singleton),默认在容器启动时初始化(除非配置 @Lazy)。

    • 如果 Bean 是原型(Prototype),每次请求时都会创建新实例。

 (2) 属性赋值(Population)

  • 依赖注入(DI)

    • 通过 @Autowired@Value@Resource 注入属性。

    • 如果存在循环依赖,Spring 使用三级缓存解决:

      • singletonFactories(存放未完全初始化的 Bean)

      • earlySingletonObjects(存放提前暴露的 Bean)

      • singletonObjects(存放完全初始化的 Bean)。

(3) Aware 接口回调 

  • 作用:让 Bean 感知容器的某些组件(如 ApplicationContextBeanName)。

  • 常见 Aware 接口:

    • BeanNameAware(获取 Bean 的名称)

    • BeanFactoryAware(获取 BeanFactory

    • ApplicationContextAware(获取 ApplicationContext

    • EnvironmentAware(获取环境变量)

  • 示例

@Component
public class MyBean implements BeanNameAware, ApplicationContextAware {
    @Override
    public void setBeanName(String name) {
        System.out.println("Bean name: " + name);
    }

    @Override
    public void setApplicationContext(ApplicationContext context) {
        System.out.println("ApplicationContext: " + context);
    }
}

(4) BeanPostProcessor 前置处理

  • 作用:在 Bean 初始化前后进行额外处理(如 AOP 代理、@PostConstruct 调用)。

  • 关键方法

    • postProcessBeforeInitialization():初始化前调用。

    • postProcessAfterInitialization():初始化后调用。

  • 示例

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println("Before init: " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("After init: " + beanName);
        return bean;
    }
}

 (5) 初始化(Initialization)

  • 触发方式

    • @PostConstruct 注解的方法。

    • InitializingBean.afterPropertiesSet() 接口方法。

    • XML 配置的 init-method

  • 示例

@Component
public class MyBean implements InitializingBean {
    @PostConstruct
    public void init() {
        System.out.println("@PostConstruct called");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("InitializingBean.afterPropertiesSet() called");
    }

    public void customInit() {
        System.out.println("Custom init-method called");
    }
}

(6) BeanPostProcessor 后置处理

  • 典型应用

    • AOP 动态代理(AbstractAutoProxyCreator)。

    • 事务管理(InfrastructureAdvisorAutoProxyCreator)。

(7) Bean 就绪(Ready)

  • 单例 Bean:存入 singletonObjects 缓存,供后续使用。

  • 原型 Bean:每次请求时重新创建。

(8) 销毁(Destruction)

  • 触发方式

    • @PreDestroy 注解的方法。

    • DisposableBean.destroy() 接口方法。

    • XML 配置的 destroy-method

  • 示例

@Component
public class MyBean implements DisposableBean {
    @PreDestroy
    public void cleanup() {
        System.out.println("@PreDestroy called");
    }

    @Override
    public void destroy() {
        System.out.println("DisposableBean.destroy() called");
    }

    public void customDestroy() {
        System.out.println("Custom destroy-method called");
    }
}

2. 完整的生命周期流程图 


    A[Bean 实例化] --> B[属性赋值(依赖注入)]
    B --> C[Aware 接口回调]
    C --> D[BeanPostProcessor 前置处理]
    D --> E[初始化(@PostConstruct/afterPropertiesSet/init-method)]
    E --> F[BeanPostProcessor 后置处理]
    F --> G[Bean 就绪]
    G --> H[容器关闭]
    H --> I[销毁(@PreDestroy/destroy/destroy-method)]

3. 关键扩展点总结

扩展点触发时机典型应用场景
BeanFactoryPostProcessorBean 定义加载后,实例化前修改 Bean 定义(如占位符替换)
BeanPostProcessorBean 初始化前后AOP 代理、注解处理(如 @Autowired
InitializingBean属性注入完成后自定义初始化逻辑
DisposableBean容器关闭时资源释放(如关闭文件句柄)

4. 常见问题 

(1) @PostConstruct vs InitializingBean vs init-method

  • 执行顺序

    1. @PostConstruct

    2. InitializingBean.afterPropertiesSet()

    3. init-method

  • 推荐:优先使用 @PostConstruct(更符合注解驱动编程风格)。

(2) 如何避免循环依赖?

  • 使用 @Lazy 延迟加载。

  • 避免字段注入,改用构造器注入:

@Component
public class ServiceA {
    private final ServiceB serviceB;
    
    public ServiceA(ServiceB serviceB) {
        this.serviceB = serviceB;
    }
}

(3) 如何手动销毁 Bean?

  • 对于原型 Bean,Spring 不会自动销毁,需手动调用 destroy()

5. 最佳实践

  1. 避免在初始化阶段执行耗时操作,防止应用启动变慢。

  2. 优先使用 @PostConstruct 和 @PreDestroy,而非 InitializingBean/DisposableBean

  3. 谨慎使用 Aware 接口,避免与容器强耦合。

  4. 合理使用 BeanPostProcessor,适用于框架级扩展(如 AOP)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值