Bean生命周期(一) 浅尝知味

在Spring体系中,对象的实例(Bean)都是交给Spring容器进行管理的,但是对于Bean在Spring中是创建及销毁流程,很多人都只有一个模糊的概念,今天我们就来认真地探寻一下Bean生命周期的问题。

生命周期图

首先,给大家晒上一张我画的生命周期图,当然这并不是完整的流程,像 InstantiationAwareBeanPostProcessor 里面的 postProcessProperties() 在图上就没有体现,为啥不画呢? 因为目前大家基本上都使用SpringBoot在做项目开发,如果需要给Bean的属性注入某些值的话,基本都是由@Bean声明一个方法然后再给其设置上预期的值,这样的话,就不会经过上面的这个方法了。另外,BeanFactoryPostProcessor 这里也没有画,因为BeanFactoryPostProcessor是处理BeanFactory的,在getBean()方法调用前已经执行过了,不在Bean的生命周期范围内。

Bean生命周期图示

整张图分为两个部分,横线以上是Bean的初始化流程,下面是Bean的销毁流程。

初始化流程

为方便记忆,我将初始化流程分为三条支线,当然,实际代码的逻辑层次上不是这么划分的:

  1. 第一条线(蓝色):创建Bean前后,包裹着InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation()postProcessAfterInstantiation() 方法,一前一后,根据方法名可以很好的区分。
  2. 第二条线(绿色):Aware相关钩子方法调用,以BeanNameAwareBeanFactoryAwareApplicationContextAware依次组成,具体调用的方法名可以使用类名推断出来。(这里我没有画BeanClassLoaderAware,因为个人认为使用不多,它位于BeanNameAwareBeanFactoryAware之间)
  3. 第三条线(黄色):由BeanPostProcessor包裹头尾,中间部分由@PostConstructInitializingBean.afterPropertiesSet()init-method三个节点依次组成。

销毁流程

销毁流程比较简单,由@PreDestroyDisposableBean.destroy()destroy-method三个部分组成,细心的同学会发现它与初始化的第三条线是一一对应的,也就是记住了初始化流程中的第三条线,销毁流程也就记住了。

对应映射关系整理如下:

初始化销毁
@PostConstruct@PreDestroy
InitializingBeanDisposableBean
init-methoddestroy-method

实验论证

为了印证上面的内容,我准备了一个实验,通过该实验可能观察到Bean创建及销毁的整个流程。

首先,使用 https://start.spring.io 创建一个最简单的SpringBoot工程(版本号:2.1.8),然后在创建一个自定义的Bean对象LifecycleBean实现BeanFactoryAware, ApplicationContextAware,InitializingBean, DisposableBean等接口。

public class LifecycleBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware,
        InitializingBean, DisposableBean {

    public LifecycleBean() {
        Printer.print("new Bean()");
    }

    @Override
    public void setBeanName(String s) {
        Printer.print("BeanNameAware.setBeanName()");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        Printer.print("BeanFactoryAware.setBeanFactory()");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Printer.print("ApplicationContextAware.setApplicationContext()");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Printer.print("InitializingBean.afterPropertiesSet()");
    }

    @Override
    public void destroy() throws Exception {
        Printer.print("DisposableBean.destroy()");
    }

    public void initMethod() {
        Printer.print("init-method");
    }

    public void destroyMethod() {
        Printer.print("destroy-method");
    }

    @PostConstruct
    public void postConstruct() {
        Printer.print("@PostConstruct");
    }

    @PreDestroy
    public void preDestory() {
        Printer.print("@PreDestroy");
    }

}

另外,为了将LifecycleBean委托给Spring的容器管理,定义一个LifecycleConfiguration配置类,并在其中指定LifecycleBeaninit-methoddestroy-method方法。

@Configuration
public class LifecycleConfiguration {

    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
    public LifecycleBean lifecycleBean() {
        return new LifecycleBean();
    }

}

然后,再定义一个LifecycleInstantiationBeanPostProcessor用于验证InstantiationAwareBeanPostProcessor的执行节点。

@Component
public class LifecycleInstantiationBeanPostProcessor
        implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanClass == LifecycleBean.class) {
            Printer.print("InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (bean instanceof LifecycleBean) {
            Printer.print("InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()");
        }
        return false;
    }

}

最后,再为BeanPostProcessor定义一个实现类LifecycleBeanPostProcessor

@Component
public class LifecycleBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof LifecycleBean) {
            Printer.print("BeanPostProcessor.postProcessBeforeInitialization()");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof LifecycleBean) {
            Printer.print("BeanPostProcessor.postProcessAfterInitialization()");
        }
        return bean;
    }

}

在上述代码实现中,输入借用了一个自定义的工具类Printer,其作用给流程节点加上编号,让流程更加直观,这里,我也贴一下它的简单实现:

public class Printer {

    private static AtomicInteger lineNumber = new AtomicInteger(0);

    public static void print(String value) {
        System.out.println(lineNumber.addAndGet(1) + " : " + value);
    }

}

实现案例准备完毕后,运行一下应用,得出输出内容如下:

1 : InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
2 : new Bean()
3 : InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
4 : BeanNameAware.setBeanName()
5 : BeanFactoryAware.setBeanFactory()
6 : ApplicationContextAware.setApplicationContext()
7 : BeanPostProcessor.postProcessBeforeInitialization()
8 : @PostConstruct
9 : InitializingBean.afterPropertiesSet()
10 : init-method
11 : BeanPostProcessor.postProcessAfterInitialization()
2019-10-01 18:35:58.935 INFO 1192 — [main] SpringApplication : Started SpringApplication in 1.783 seconds
12 : @PreDestroy
13 : DisposableBean.destroy()
14 : destroy-method

从输出内容来看,中间有一段应用启动完成的日志,将Bean创建流程与销毁流程完全划分开,而创建和销毁的输出内容我们上图表述的一致,故流程得证。

在这里插入图片描述

迎您扫一扫上面的微信公众号,订阅我的博客!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值