问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

一文详解Spring Bean的生命周期

创作时间:
作者:
@小白创作中心

一文详解Spring Bean的生命周期

引用
CSDN
1.
https://m.blog.csdn.net/Kerwin_D/article/details/145446317

本文详细讲解了Spring框架中Bean的生命周期,包括实例化、属性赋值、初始化、使用中和销毁五个阶段。通过源码分析和单元测试的方式,深入描述了每个阶段的具体实现,并提供了具体的代码示例。此外,还介绍了Aware接口的作用以及init-method和destroy-method的调用时机。

Bean生命周期概述

Bean的生命周期大致分为五个阶段:

  1. 实例化:Spring首先使用构造方法或者工厂方法创建一个Bean的实例。在这个阶段,Bean只是一个空的Java对象,还未设置任何属性。

  2. 属性赋值:Spring将配置文件中的属性值或依赖的Bean注入到该Bean中。这个过程称为依赖注入,确保Bean所需的所有依赖都被注入。

  3. 初始化:Spring调用afterPropertiesSet方法,或通过配置文件指定的init-method方法,完成初始化。

  4. 使用中:Bean准备好可以使用了。

  5. 销毁:在容器关闭时,Spring会调用destroy方法,完成Bean的清理工作。

源码分析

接下来从源码角度讲解Bean的生命周期:

  • 实例化:Spring容器根据Bean的定义创建Bean的实例,相当于执行构造方法,也就是new一个对象。

  • 属性赋值:相当于执行setter方法为字段赋值。

  • 初始化:初始化阶段允许执行自定义的逻辑,比如设置某些必要的属性值、开启资源、执行预加载操作等,以确保Bean在使用之前是完全配置好的。

  • 销毁:相当于执行null,释放资源。

可以在源码AbstractAutowireCapableBeanFactory中的doCreateBean方法中,看到Bean的前三个生命周期:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // 实例化阶段
        instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    }
    ...
    Object exposedObject = bean;
    try {
        // 属性赋值阶段
        this.populateBean(beanName, mbd, instanceWrapper);
        // 初始化阶段
        exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    } catch (Throwable var18) {
        ...
    }
    ...
}

源码位置如下:

至于销毁,是在容器关闭的时候调用的,详见ConfigurableApplicationContextclose方法。

单元测试演示

接下来在一个已有的Spring Boot项目中通过单元测试的形式来展示Spring Bean的生命周期。

创建LifecycleDemoBean类

public class LifecycleDemoBean implements InitializingBean, DisposableBean {
    // 使用@Value注解注入属性值,这里演示了如何从配置文件中读取值
    // 如果配置文件中没有定义lifecycle.demo.bean.name,则使用默认值"default name"
    @Value("${lifecycle.demo.bean.name:default name}")
    private String name;
    // 构造方法:在Bean实例化时调用
    public LifecycleDemoBean() {
        System.out.println("LifecycleDemoBean: 实例化");
    }
    // 属性赋值:Spring通过反射调用setter方法为Bean的属性注入值
    public void setName(String name) {
        System.out.println("LifecycleDemoBean: 属性赋值");
        this.name = name;
    }
    // 使用@PostConstruct注解的方法:在Bean的属性赋值完成后调用,用于执行初始化逻辑
    @PostConstruct
    public void postConstruct() {
        System.out.println("LifecycleDemoBean: @PostConstruct(初始化)");
    }
    // 实现InitializingBean接口:afterPropertiesSet方法在@PostConstruct注解的方法之后调用
    // 用于执行更多的初始化逻辑
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("LifecycleDemoBean: afterPropertiesSet(InitializingBean)");
    }
    // 自定义初始化方法:在XML配置或Java配置中指定,执行特定的初始化逻辑
    public void customInit() {
        System.out.println("LifecycleDemoBean: customInit(自定义初始化方法)");
    }
    // 使用@PreDestroy注解的方法:在容器销毁Bean之前调用,用于执行清理工作
    @PreDestroy
    public void preDestroy() {
        System.out.println("LifecycleDemoBean: @PreDestroy(销毁前)");
    }
    // 实现DisposableBean接口:destroy方法在@PreDestroy注解的方法之后调用
    // 用于执行清理资源等销毁逻辑
    @Override
    public void destroy() throws Exception {
        System.out.println("LifecycleDemoBean: destroy(DisposableBean)");
    }
    // 自定义销毁方法:在XML配置或Java配置中指定,执行特定的清理逻辑
    public void customDestroy() {
        System.out.println("LifecycleDemoBean: customDestroy(自定义销毁方法)");
    }
}

实例化阶段

实例化是创建Bean实例的过程,即在内存中为Bean对象分配空间。这一步是通过调用Bean的构造方法完成的。

public LifecycleDemoBean() {
    System.out.println("LifecycleDemoBean: 实例化");
}

在这里,当Spring创建LifecycleDemoBean的实例时,会调用其无参数的构造方法,这个过程就是实例化。

属性赋值阶段

在实例化之后,Spring将根据Bean定义中的配置信息,通过反射机制为Bean的属性赋值。

@Value("${lifecycle.demo.bean.name:default name}")
private String name;
public void setName(String name) {
    System.out.println("LifecycleDemoBean: 属性赋值");
    this.name = name;
}

@Value注解和setter方法体现了属性赋值的过程。@Value注解让Spring注入配置值(或默认值),setter方法则是属性赋值的具体操作。

初始化阶段

初始化阶段允许执行自定义的初始化逻辑,比如检查必要的属性是否已经设置、开启资源等。Spring提供了多种方式来配置初始化逻辑。

  1. 使用@PostConstruct注解的方法
@PostConstruct
public void postConstruct() {
    System.out.println("LifecycleDemoBean: @PostConstruct(初始化)");
}

@PostConstruct注解的方法在Bean的所有属性都被赋值后,且用户自定义的初始化方法之前调用。

  1. 实现InitializingBean接口的afterPropertiesSet方法
@Override
public void afterPropertiesSet() throws Exception {
    System.out.println("LifecycleDemoBean: afterPropertiesSet(InitializingBean)");
}

afterPropertiesSet方法提供了另一种初始化Bean的方式,也是在所有属性赋值后调用。

  1. 自定义初始化方法
public void customInit() {
    System.out.println("LifecycleDemoBean: customInit(自定义初始化方法)");
}

需要在配置类中指定初始化方法:

@Bean(initMethod = "customInit")
public LifecycleDemoBean lifecycleDemoBean() {
    return new LifecycleDemoBean();
}

销毁阶段

销毁阶段允许执行自定义的销毁逻辑,比如释放资源。类似于初始化阶段,Spring也提供了多种方式来配置销毁逻辑。

  1. 使用@PreDestroy注解的方法
@PreDestroy
public void preDestroy() {
    System.out.println("LifecycleDemoBean: @PreDestroy(销毁前)");
}

@PreDestroy注解的方法在Bean被销毁前调用。

  1. 实现DisposableBean接口的destroy方法
@Override
public void destroy() throws Exception {
    System.out.println("LifecycleDemoBean: destroy(DisposableBean)");
}

destroy方法提供了另一种销毁Bean的方式,也是在Bean被销毁前调用。

  1. 自定义销毁方法
public void customDestroy() {
    System.out.println("LifecycleDemoBean: customDestroy(自定义销毁方法)");
}

需要在配置类中指定销毁方法:

@Bean(destroyMethod = "customDestroy")
public LifecycleDemoBean lifecycleDemoBean() {
    return new LifecycleDemoBean();
}

注册Bean并指定自定义初始化方法和销毁方法

@Configuration
public class LifecycleDemoConfig {
    @Bean(initMethod = "customInit", destroyMethod = "customDestroy")
    public LifecycleDemoBean lifecycleDemoBean() {
        return new LifecycleDemoBean();
    }
}

编写单元测试

@SpringBootTest
public class LifecycleDemoTest {
    @Autowired
    private ApplicationContext context;
    @Test
    public void testBeanLifecycle() {
        System.out.println("获取LifecycleDemoBean实例...");
        LifecycleDemoBean bean = context.getBean(LifecycleDemoBean.class);
    }
}

运行单元测试,查看控制台输出:

LifecycleDemoBean: 实例化
LifecycleDemoBean: @PostConstruct(初始化)
LifecycleDemoBean: afterPropertiesSet(InitializingBean)
LifecycleDemoBean: customInit(自定义初始化方法)
获取LifecycleDemoBean实例...
LifecycleDemoBean: @PreDestroy(销毁前)
LifecycleDemoBean: destroy(DisposableBean)
LifecycleDemoBean: customDestroy(自定义销毁方法)

Aware接口的作用

通过实现Aware接口,Bean可以获取Spring容器的相关信息,如BeanFactory、ApplicationContext等。常见Aware接口有:

接口
作用
BeanNameAware
获取当前Bean的名称。
BeanFactoryAware
获取当前Bean所在的BeanFactory实例,可以直接操作容器。
ApplicationContextAware
获取当前Bean所在的ApplicationContext实例。
EnvironmentAware
获取Environment对象,用于获取配置文件中的属性或环境变量。
ServletContextAware
在Web环境下获取ServletContext实例,访问Web应用上下文。
ResourceLoaderAware
获取ResourceLoader对象,用于加载资源文件(如类路径文件或URL)。

init-method和destroy-method的调用时机

  • init-method在Bean初始化阶段调用,依赖注入完成后且postProcessBeforeInitialization调用之后执行。
  • destroy-method在Bean销毁阶段调用,容器关闭时调用。

本文原文来自CSDN

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号