器 | Spring Bean 生命周期(一)

593 阅读3分钟

本篇文章介绍spring bean 生命周期的各个阶段,包括初始化、和销毁过程。

一、bean 的生命周期

当Spring容器启动时,通过不同的方式实例化完成bean以后,bean将放入容器中进行管理。放入到容器的bean需要执行一系列初始化后,才能使其进行可用的状态。之后,当我们不再需要bean时,bean将会被从容器中移除。

SpringBeanFactory在bean的全生命周期过程中参与管理,起到至关重要的作用。

1.1 启动初始化过程

在容器启动后,SpringBeanFactory就会开始工作。在整个初始化的过程中,严格意义上来讲,实际上会有三个层级的初始化处理,包括工厂级别的处理(BeanFactoryPostProcessor等)、容器级别的处理(InstantiationAwareBeanPostProcessorBeanPostProcessor等)、Bean级别的处理(专属某一个bean)。

工厂级别的处理,还有容器级别的处理基本上是Spring框架层面的内容,不做太深入的研究,在代码中引入这些处理,会加深代码对Spring的耦合。不过这篇文章会简单说一下可能会使用到的BeanPostProcessor

image.png

图上是bean的初始化过程,除开BeanPostProcessor后置处理器,其它的过程都是Bean级别的初始化处理。

  • 初始化开始是java本身的实例化构造对象
  • 接着set依赖注入(SDI)
  • 再接着通过*Aware接口让bean感知Spring容器资源,比如beanName,ApplicationContext
  • 然后是容器级别的BeanPostProcessor##PostProcessorBeforeInitializationbean初始化前置操作
  • 接着是执行有注解@PostConstruct的方法
  • 然后是执行接口InitializationBean#AfterPropertiesSet的实现
  • 其次是执行@Bean#initMethod
  • 最后是容器级别的BeanPostProcessor##PostProcessorBeforeInitializationbean初始化后置操作,至此bean初始化完成

1.2 容器关闭销毁过程

容器执行shutdown关闭操作后,bean就会开始一系列的销毁操作,相比较初始化操作,销毁步骤少了很多。

image.png

  • bean销毁开始执行有注解@Predestory的方法
  • 然后是执行接口DisposeBean#destory的实现
  • 最后执行@Bean#destroyMethod,至此,销毁完成

二、代码示例

下面通过简单的打印示例演示Spring bean的生命周期。

首先创建一个业务bean类,实现接口InitializingBean, DisposableBean, ApplicationContextAware, BeanNameAware

public class TestBean implements InitializingBean, DisposableBean, ApplicationContextAware, BeanNameAware {

    private String name;

    public TestBean(String name) {
        System.out.println("-------------construct--------------");
        this.name = name;
    }

    public void setName(String name) {
        System.out.println("-------------set method--------------");
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("--------InitializingBean#afterPropertiesSet-----");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("---------DisposableBean#destroy--------------");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("---------BeanNameAware#setApplicationContext----");
    }


    @Override
    public void setBeanName(String s) {
        System.out.println("----------ApplicationContextAware#setBeanName----");
    }

    public void initFromBean(){
        System.out.println("----------initFrom@Bean----------");
    }

    public void destroyFromBean(){
        System.out.println("----------destroyFrom@Bean---------------");
    }

    @PostConstruct
    public void customInit()
    {
        System.out.println("---------@PostConstruct----------");
    }

    @PreDestroy
    public void customDestroy()
    {
        System.out.println("---------@PreDestroy--------");
    }
}

然后实现自定义的BeanPostProcessor

public class TestBeanProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof TestBean){
            System.out.println("------------BeanPostProcessor#postProcessAfterInitialization :" + beanName);
        }
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof TestBean){
            System.out.println("------------BeanPostProcessor#postProcessBeforeInitialization :" + beanName);
        }
        return bean;
    }
}

最后实现一个Spring启动类

@SpringBootApplication
@Import({
        TestBeanProcessor.class
})
public class SpringsApplication {

    public static void main(String[] args) {
        final ConfigurableApplicationContext ctx = SpringApplication.run(SpringsApplication.class, args);
        ctx.close();
    }

    @ConditionalOnMissingBean
    @Bean(initMethod = "initFromBean",destroyMethod = "destroyFromBean")
    public TestBean testBean(){
        return new TestBean("testBean"){{
            setName("testName");
        }};
    }
}

启动应用程序,打印结果如下

启动初始化过程

微信截图_20210413092628.png

关闭容器销毁过程

微信截图_20210413092635.png

三、总结

InitializingBeanDisposableBean不是初始化 和销毁bean 的首选方法,因为它将 bean 类与 spring 容器紧密耦合。更好的方法是在bean 定义中使用 init-method,destroyMethod属性。

从 Spring 2.5开始,还可以使用注释来指定使用@postconstruct @predestroy 介入bean生命周期。

预告下一篇将会讲到BeanPostProcessor,以及*Aware