Skip to content

Spring Bean的生命周期

要理解Spring Bean的生命周期,核心是掌握从Bean的创建→初始化→使用→销毁的完整流程,以及Spring容器在每个阶段对Bean的干预逻辑。以下是**细致到“每一步做什么、涉及哪些接口/注解、顺序如何”**的拆解: bean生命周期图.png

一、先明确:Spring生命周期的核心对象

Spring的生命周期管理依赖两个核心组件:

  1. BeanFactory:Spring的“Bean工厂”,负责Bean的创建、配置、管理(最基础的容器)。
  2. ApplicationContext:BeanFactory的扩展,增加了事件发布、国际化、AOP等功能,默认自动初始化单例Bean(BeanFactory是懒加载)。

我们常说的“Spring生命周期”,本质是ApplicationContext管理下的Bean生命周期(更贴近实际开发场景)。

二、Spring Bean生命周期的完整流程(单例Bean)

单例Bean(默认Scope)的生命周期与容器同生共死(容器启动时创建,容器关闭时销毁)。以下是按执行顺序排列的11个关键步骤,结合接口/注解/配置的作用:

1. 阶段1:Bean定义的加载与解析

  • 操作:Spring容器启动时,加载@Component@Bean、XML <bean>Bean定义(BeanDefinition),解析成BeanDefinition对象(包含Bean的类名、属性、Scope、初始化方法等元数据)。
  • 举例@Component标注的类会被ComponentScan扫描到,生成对应的BeanDefinition

2. 阶段2:Bean的实例化(Instantiation)

  • 操作:Spring根据BeanDefinition的元数据,创建Bean的实例(内存中分配对象)。
  • 实例化方式
    • 默认:调用无参构造器(若有参,需配合@Autowired<constructor-arg>注入)。
    • 静态工厂方法:如@Bean public static MyBean createBean()(调用静态方法创建实例)。
    • 实例工厂方法:如@Bean public MyBean createBean(OtherBean other)(调用现有Bean的方法创建实例)。
  • 注意:此时Bean的属性(如@Autowired标注的字段)还未赋值,只是一个“空壳”对象。

3. 阶段3:属性注入(Populate Properties)

  • 操作:Spring根据BeanDefinition中的配置(如@Autowired@Value<property>),将依赖的Bean或值注入到当前Bean的属性中
  • 关键机制
    • 自动注入(Autowiring):通过类型(byType)或名称(byName)匹配依赖。
    • 外部值注入:通过@Value("${config.key}")读取配置文件的值。
  • 举例
    java
    @Component
    public class UserService {
        @Autowired // 属性注入
        private UserDao userDao;
    }
  • 注意:属性注入完成后,Bean的基本状态才完整

4. 阶段4:Aware接口的回调(注入容器上下文)

  • 操作:若Bean实现了Aware接口(Spring提供的“感知”接口),Spring会将对应的容器资源注入到Bean中,让Bean能访问容器的内部信息。
  • 常见Aware接口及作用
    接口方法作用
    BeanNameAwaresetBeanName(String name)注入当前Bean在容器中的名称
    BeanFactoryAwaresetBeanFactory(BeanFactory)注入BeanFactory(容器本身)
    ApplicationContextAwaresetApplicationContext(ApplicationContext)注入ApplicationContext(更强大的容器)
    ResourceLoaderAwaresetResourceLoader(ResourceLoader)注入资源加载器(用于读取文件)
  • 举例
    java
    @Component
    public class MyBean implements BeanNameAware {
        @Override
        public void setBeanName(String name) {
            System.out.println("当前Bean的名称:" + name); // 输出:myBean
        }
    }
  • 顺序:Aware接口的回调在属性注入之后(因为需要Bean先有完整的属性)。

5. 阶段5:BeanPostProcessor的前置处理(增强Bean)

  • 操作:若容器中有BeanPostProcessor(Bean后置处理器),Spring会调用其postProcessBeforeInitialization方法,在初始化前对Bean进行增强
  • 作用:这是Spring扩展的核心点(如AOP、事务代理都是通过此机制实现)。
  • 举例:自定义BeanPostProcessor:
    java
    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor {
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof UserService) {
                System.out.println("初始化前增强:" + beanName);
            }
            return bean; // 返回增强后的Bean(若不修改则返回原对象)
        }
    }
  • 注意:所有Bean都会经过BeanPostProcessor的处理(除非过滤)。

6. 阶段6:初始化(Initialization)

  • 操作:Bean完成属性注入和前置增强后,执行自定义的初始化逻辑(如初始化连接池、加载缓存)。
  • 初始化的3种方式(执行顺序从先到后)
    1. @PostConstruct注解(JSR-250规范):标注在非静态方法上,Spring通过CommonAnnotationBeanPostProcessor处理。
    2. InitializingBean接口(Spring自带):实现afterPropertiesSet()方法。
    3. init-method配置:通过XML <bean init-method="init">@Bean(initMethod = "init")指定。
  • 举例
    java
    @Component
    public class UserService implements InitializingBean {
        @PostConstruct
        public void postConstruct() {
            System.out.println("1. @PostConstruct执行");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("2. InitializingBean执行");
        }
    
        public void init() { // 对应@Bean(initMethod = "init")
            System.out.println("3. init-method执行");
        }
    }
  • 执行顺序验证@PostConstructInitializingBeaninit-method

7. 阶段7:BeanPostProcessor的后置处理(最终增强)

  • 操作:调用BeanPostProcessor的postProcessAfterInitialization方法,在初始化后对Bean进行最终增强
  • 典型场景:AOP代理就是在此步骤生成的——若Bean需要被代理(如@Transactional标注),Spring会返回代理对象而非原Bean。
  • 举例(续阶段5的MyBeanPostProcessor):
    java
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof UserService) {
            System.out.println("初始化后增强:" + beanName);
        }
        return bean;
    }

8. 阶段8:Bean的使用(In Use)

  • 操作:此时Bean已完全初始化,可以被容器或用户获取并使用(如通过context.getBean(UserService.class)获取)。
  • 注意:单例Bean会被缓存到容器的singletonObjectsmap中,后续获取直接从缓存取。

9. 阶段9:容器关闭前的准备(Pre-Shutdown)

  • 操作:当容器即将关闭(如context.close()或JVM退出),Spring会触发销毁前的准备(如发布ContextClosedEvent事件)。

10. 阶段10:销毁(Destruction)

  • 操作:执行自定义的销毁逻辑(如关闭连接池、释放文件流)。
  • 销毁的3种方式(执行顺序从先到后)
    1. @PreDestroy注解(JSR-250规范):标注在非静态方法上。
    2. DisposableBean接口(Spring自带):实现destroy()方法。
    3. destroy-method配置:通过XML <bean destroy-method="destroy">@Bean(destroyMethod = "destroy")指定。
  • 举例
    java
    @Component
    public class UserService implements DisposableBean {
        @PreDestroy
        public void preDestroy() {
            System.out.println("1. @PreDestroy执行");
        }
    
        @Override
        public void destroy() throws Exception {
            System.out.println("2. DisposableBean执行");
        }
    
        public void destroy() { // 对应@Bean(destroyMethod = "destroy")
            System.out.println("3. destroy-method执行");
        }
    }
  • 执行顺序验证@PreDestroyDisposableBeandestroy-method

11. 阶段11:Bean的回收(GC)

  • 操作:销毁完成后,Bean不再被容器引用,最终被JVM垃圾回收

三、不同Scope对生命周期的影响

Spring的Scope(作用域)决定了Bean的创建时机和生命周期:

  1. Singleton(单例,默认)
    • 生命周期:与容器一致(容器启动时创建,容器关闭时销毁)。
    • 场景:无状态的Bean(如Service、Dao)。
  2. Prototype(原型)
    • 生命周期:每次getBean()时创建,容器不负责销毁(需用户手动处理)。
    • 场景:有状态的Bean(如Request级别的Model)。
  3. Request(请求域,Web场景)
    • 生命周期:每个HTTP请求创建一个Bean,请求结束时销毁。
  4. Session(会话域,Web场景)
    • 生命周期:每个HTTP Session创建一个Bean,会话过期时销毁。
  5. Application(应用域,Web场景)
    • 生命周期:与ServletContext一致(Web应用启动时创建,关闭时销毁)。

四、关键接口/注解的执行顺序总结

将前面的步骤简化为核心顺序链(单例Bean):

Bean定义加载 → 实例化(构造器) → 属性注入(@Autowired) → Aware接口(BeanNameAware) → 
BeanPostProcessor前置处理 → 初始化(@PostConstruct → InitializingBean → init-method) → 
BeanPostProcessor后置处理 → 使用 → 销毁(@PreDestroy → DisposableBean → destroy-method) → GC

五、为什么要理解Spring生命周期?

  1. 自定义扩展:通过BeanPostProcessorAware接口等扩展Spring功能(如自定义注解、AOP)。
  2. 排查问题:解决Bean初始化失败、依赖注入异常等问题(如@PostConstruct执行顺序错误)。
  3. 资源管理:确保资源在销毁时正确释放(如数据库连接池、Redis连接)。

六、示例:完整生命周期的代码验证

以下代码可以直观看到生命周期的执行顺序:

java
// 1. 自定义Bean(覆盖主要生命周期步骤)
@Component
public class LifeCycleBean implements BeanNameAware, InitializingBean, DisposableBean {
    // 阶段2:实例化(构造器)
    public LifeCycleBean() {
        System.out.println("1. 实例化:构造器执行");
    }

    // 阶段3:属性注入(@Autowired)
    @Autowired
    public void setUserDao(UserDao userDao) {
        System.out.println("2. 属性注入:UserDao已注入");
    }

    // 阶段4:Aware接口(BeanNameAware)
    @Override
    public void setBeanName(String name) {
        System.out.println("3. Aware接口:Bean名称为" + name);
    }

    // 阶段5:BeanPostProcessor前置处理(需自定义BeanPostProcessor)
    // 阶段6:初始化(@PostConstruct → InitializingBean → init-method)
    @PostConstruct
    public void postConstruct() {
        System.out.println("4. 初始化:@PostConstruct执行");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("5. 初始化:InitializingBean执行");
    }

    public void initMethod() { // 需配置@Bean(initMethod = "initMethod")
        System.out.println("6. 初始化:init-method执行");
    }

    // 阶段7:BeanPostProcessor后置处理(需自定义BeanPostProcessor)
    // 阶段8:使用(假设被其他Bean调用)
    public void doSomething() {
        System.out.println("7. 使用:Bean正在工作");
    }

    // 阶段10:销毁(@PreDestroy → DisposableBean → destroy-method)
    @PreDestroy
    public void preDestroy() {
        System.out.println("8. 销毁:@PreDestroy执行");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("9. 销毁:DisposableBean执行");
    }

    public void destroyMethod() { // 需配置@Bean(destroyMethod = "destroyMethod")
        System.out.println("10. 销毁:destroy-method执行");
    }
}

// 2. 自定义BeanPostProcessor
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof LifeCycleBean) {
            System.out.println("BeanPostProcessor:初始化前增强");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof LifeCycleBean) {
            System.out.println("BeanPostProcessor:初始化后增强");
        }
        return bean;
    }
}

// 3. 配置类(开启组件扫描)
@Configuration
@ComponentScan("com.example")
public class AppConfig {
    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
    public LifeCycleBean lifeCycleBean() {
        return new LifeCycleBean();
    }
}

// 4. 启动类
public class Application {
    public static void main(String[] args) {
        // 启动容器(ApplicationContext)
        try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class)) {
            // 获取Bean并使用
            LifeCycleBean bean = context.getBean(LifeCycleBean.class);
            bean.doSomething();
        } // 容器自动关闭(触发销毁逻辑)
    }
}

七、输出结果验证顺序

运行启动类后,输出顺序如下(对应生命周期步骤):

1. 实例化:构造器执行
2. 属性注入:UserDao已注入
3. Aware接口:Bean名称为lifeCycleBean
BeanPostProcessor:初始化前增强
4. 初始化:@PostConstruct执行
5. 初始化:InitializingBean执行
6. 初始化:init-method执行
BeanPostProcessor:初始化后增强
7. 使用:Bean正在工作
8. 销毁:@PreDestroy执行
9. 销毁:DisposableBean执行
10. 销毁:destroy-method执行

总结

Spring的生命周期是**“容器主导、Bean参与”的过程:容器负责Bean的创建、注入、管理,Bean通过接口/注解参与自定义逻辑。理解生命周期的核心是掌握各个阶段的顺序和关键扩展点**,这是Spring进阶的基础。