网站Logo Ilren 小记

Spring Bean 生命周期详解

jack
8
2021-07-20

引言

在使用 Spring 开发时,Bean 是我们接触最频繁的组件。了解 Spring Bean 的生命周期,不仅能帮我们更好地掌握 Spring 容器的工作原理,还能在实际项目中优雅地管理资源、执行初始化或清理逻辑。

本文将从整体流程出发,逐步拆解 Spring Bean 的生命周期,并配以图示、代码示例与实战技巧,带你全面理解 Bean 的“生老病死”。

🌱 一、Spring Bean 生命周期概览

Spring Bean 生命周期的大致流程如下:

  1. 实例化(Instantiation)

  2. 属性赋值(Populate Properties)

  3. 初始化前(BeanPostProcessor#postProcessBeforeInitialization)

  4. 初始化(InitializingBean / 自定义 init 方法)

  5. 初始化后(BeanPostProcessor#postProcessAfterInitialization)

  6. Bean 可用了(应用层使用)

  7. 销毁前(DisposableBean / 自定义 destroy 方法)

📌 图示如下:

🛠 二、生命周期关键接口与方法

Spring 提供了几个钩子接口和配置方式,让我们可以在生命周期的不同阶段做事情。

1. InitializingBean 接口

public class MyBean implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("Bean 初始化完成!");
    }
}

✅ 建议只在需要访问所有属性后再执行逻辑时使用。

2. 自定义 init-method

@Bean(initMethod = "customInit")
public MyBean myBean() {
    return new MyBean();
}

public class MyBean {
    public void customInit() {
        System.out.println("自定义 init 方法被调用");
    }
}

3. DisposableBean 接口 & destroy-method

public class MyBean implements DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("Bean 被销毁");
    }
}

或者使用:

@Bean(destroyMethod = "customDestroy")
public MyBean myBean() {
    return new MyBean();
}

public class MyBean {
    public void customDestroy() {
        System.out.println("自定义 destroy 方法被调用");
    }
}

4. @PostConstruct & @PreDestroy 注解(推荐!)

public class MyBean {
    @PostConstruct
    public void init() {
        System.out.println("注解方式初始化");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("注解方式销毁");
    }
}

✅ 推荐使用注解方式,优雅、解耦、与配置无关。

5. BeanPostProcessor:真正的“增强器”

实现此接口可在 Bean 初始化前后进行拦截和增强,非常常用于 AOP、代理等场景。

@Component
public class MyPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println(beanName + " 初始化前");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println(beanName + " 初始化后");
        return bean;
    }
}

⚠️ 三、开发中的典型用法

  • 资源初始化如连接池、线程池配置

  • 属性校验或补全

  • 日志记录与监控挂钩

  • Bean代理包装增强(如事务、缓存)

  • 关闭钩子中释放资源、关闭连接等

🧠 四、总结与建议

阶段

推荐方式

初始化

@PostConstructinit-method

销毁

@PreDestroydestroy-method

增强处理

实现 BeanPostProcessor

建议:

  • 不建议过多依赖 InitializingBean / DisposableBean,它们会让类与 Spring 强耦合;

  • 使用 @PostConstruct/@PreDestroy 更现代、更符合 Spring Boot 风格;

  • 配合 SmartInitializingSingletonApplicationContextAware 可实现更复杂的逻辑。

动物装饰