spring学习笔记(四)我对spring中bean生命周期的理解

版权声明:戴明智的博客~ https://blog.csdn.net/qq_41907991/article/details/88677424

我相信大部分同学对spring中bean的生命周期都不陌生,但是如果要详细的说出每一个步骤,可能能说出来的也不多,我之前也是这样,前几天调了一下spring的源码,看了一点书,突然一下明朗了,理解了spring中bean的生命周期。接下来就跟大家分享下我的心得,有什么不对的也希望大家帮忙指正~


我们先看一下spring中bean的生命周期:

这是我在网上随便找的一张图,大家估计也看得不少,接下来我就这张图一步步分析spring为什么会这么设计bean的生命周期。

首先,我们知道spring的一大亮点就是IOC(控制反转)跟DI(依赖注入)。对于前两步,实例化对话以及设置对象属性我相信大家都没什么疑问。对应的步骤如下:

  • Bean的建立, 由BeanFactory读取Bean定义文件,并生成各个实例
  • Setter注入,执行Bean的属性依赖注入

后面的步骤,我们可以将其分为三步,

第一步,实现Aware一系列接口唤醒bean自身,使bean能感知到容器的存在。

第二步:初始化bean,这里的初始化是指实现我们自己定义的初始化方法。

第三步:销毁。

很明显,bean核心生命周期就在第二步

我们分析为什么会有第一步?为什么不直接初始化呢?

扫描二维码关注公众号,回复: 5723878 查看本文章

为了回答这个问题我们要知道,spring与spring所管理的bean默认是无状态的,即bean默认是无法感知到spring容器的。

但是为了实现bean的初始化,我们又不得不拿到容器对象,类似的代码就像这样


/**
 * @Author: dmz
 * @Description:
 * @Date: Create in 23:51 2019/3/18
 */
public class Person implements ApplicationContextAware {
    
    private ApplicationContext applicationContext;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    private String name;

    public Person(String name) {
        this.name = name;
    }
    
}

只有经过上面的步骤,我们的bean才跟spring发生了耦合,这里顺便说一下,spring中的容器有两种,一种是BeanFactory,一种是ApplicationContext。所以我们实现ApplicationContextAware 跟实现BeanFactoryAware的目的是一样,都是为了使bean感知到容器。

我们要知道的是,第一步使bean感知到容器,是为了帮助bean完成接下来的初始化。至于为什么最开始是(BeanNameAware的setBeanName(), 如果实现该接口,则执行其setBeanName方法),我相信这也不难理解,自身的优先级自然是高于容器的,在拿到容器对象前先获取自身Id也是可以理解的

对应步骤为:

  • BeanNameAware的setBeanName(), 如果实现该接口,则执行其setBeanName方法
  • BeanFactoryAware的setBeanFactory(),如果实现该接口,则执行其setBeanFactory方法
  • 若有Bean类实现了org.springframework.context.ApplicationContextAware接口,则执行其setApplicationContext()方法

接下来是第二步的分析:第二步可以拆分成三个部分:

1.初始化前:

  • BeanPostProcessor的processBeforeInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processBeforeInitialization()方法

2.执行初始化:

  • InitializingBean的afterPropertiesSet(),如果实现了该接口,则执行其afterPropertiesSet()方法
  • Bean定义文件中定义init-method

3.初始化后

  • BeanPostProcessors的processAfterInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processAfterInitialization()方法

对于这一步我们应该知道的是,BeanPostProcessor这个接口的作用,是对bean在初始化前后做一些操作

而我们自定义的initMethod方法跟实现InitializingBean,是为了帮助我们对bean进行初始化

最后是第三步:销毁

  • DisposableBean的destroy(),在容器关闭时,如果Bean类实现了该接口,则执行它的destroy()方法
  • Bean定义文件中定义destroy-method,在容器关闭时,可以在Bean定义文件中使用“destory-method”定义的方法

我们一步步分析下来就会发现,每一步的存在都有其合理性,并且顺序上也合理,不能随意打乱

经过这次我也发现,只有真正的理解才能记住,死记是记不住的,平常多调调源码帮助还是很大的。

以后工作学习中要多问问自己问什么,为什么要这样设计,为什么要这样写~~!!

猜你喜欢

转载自blog.csdn.net/qq_41907991/article/details/88677424