Spring源码解析-Bean ⽣命周期

一:简述

那什么是 Bean 的⽣命周期呢?这是⾮常基础的问题,面试过程中也经常会被问到。

二. 基础知识

2.1 什么是 IoC ?

IoC,控制反转,想必⼤家都知道,所谓的控制反转,就是把 new 对象的权利交给容器,所有的对象都被容器控 制,这就叫所谓的控制反转。

IoC 很好地体现了⾯向对象设计法则之⼀ —— 好莱坞法则:“别找我们,我们找你”,即由 IoC 容器帮对象找相应的 依赖对象并注⼊,⽽不是由对象主动去找。

理解好 IoC 的关键是要明确 “谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些⽅⾯反转了”。

谁控制谁,控制什么?

传统 Java SE 程序设计,我们直接在对象内部通过 new 进⾏创建对象,是程序主动去创建依赖对象。⽽ IoC 是由专 ⻔⼀个容器来创建这些对象,即由 IoC 容器来控制对象的创建。

  • 谁控制谁?当然是 IoC 容器控制了对象;
  • 控制什么?主要控制了外部资源获取(不只是对象,⽐如包括⽂件等)。

为何是反转,哪些⽅⾯反转了?

有反转就有正转,传统应⽤程序是由我们⾃⼰在对象中主动控制去直接获取依赖对象,也就是正转,⽽反转则是由 容器来帮忙创建及注⼊依赖对象。

  • 为何是反转?因为由容器帮我们查找及注⼊依赖对象,对象只是被动的接受依赖对象,所以是反转;
  • 哪些⽅⾯反转了?依赖对象的获取被反转了。

2.2 Bean ⽣命周期

对 Prototype Bean 来说,当⽤户 getBean 获得 Prototype Bean 的实例后,IOC 容器就不再对当前实例进⾏管 理,⽽是把管理权交由⽤户,此后再 getBean ⽣成的是新的实例。

所以我们描述 Bean 的⽣命周期,都是指的 Singleton Bean。

Bean ⽣命周期过程:

  • 实例化:第 1 步,实例化⼀个 Bean 对象;
  • 属性赋值:第 2 步,为 Bean 设置相关属性和依赖;
  • 初始化:初始化的阶段的步骤⽐较多,5、6 步是真正的初始化,第 3、4 步为在初始化前执⾏,第 7 步在初 始化后执⾏,初始化完成之后,Bean 就可以被使⽤了;
  • 销毁:第 8~10 步,第 8 步其实也可以算到销毁阶段,但不是真正意义上的销毁,⽽是先在使⽤前注册了销毁 的相关调⽤接⼝,为了后⾯第 9、10 步真正销毁 Bean 时再执⾏相应的⽅法。

整个执⾏流程稍微有些抽象,下⾯我们通过代码,来演示执⾏流程。

2.3 执⾏流程

创建⼀个 ModelBean。

public class ModelBean implements InitializingBean, BeanFactoryAware, BeanNameAware,
        DisposableBean {
    /**
     * 姓名
     */
    private String name;

    public ModelBean() {
        System.out.println("1.调⽤构造⽅法:我出⽣了!");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("2.设置属性:我的名字叫" + name);
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("3.调⽤BeanNameAware#setBeanName⽅法:我要上学了,起了个学名");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("4.调⽤BeanFactoryAware#setBeanFactory⽅法:选好学校了");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("6.InitializingBean#afterPropertiesSet⽅法:⼊学登记");
    }

    public void init() {
        System.out.println("7.⾃定义init⽅法:努⼒上学ing");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("9.DisposableBean#destroy⽅法:平淡的⼀⽣落幕了");
    }

    public void destroyMethod() {
        System.out.println("10.⾃定义destroy⽅法:睡了,别想叫醒我");
    }

    public void work() {
        System.out.println("Bean使⽤中:⼯作,只有对社会没有⽤的⼈才放假。。");
    }

}
复制代码

⾃定义⼀个后处理器 MyBeanPostProcessor。

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws
            BeansException {
        System.out.println("5.BeanPostProcessor.postProcessBeforeInitialization⽅法:到学
                校报名啦");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws
            BeansException {
        System.out.println("8.BeanPostProcessor#postProcessAfterInitialization⽅法:终于
                毕业,拿到毕业证啦!");
        return bean;
    }
}
复制代码

applicationContext.xml 配置⽂件(部分)。

<bean name="myBeanPostProcessor" class="demo.MyBeanPostProcessor" />
<bean name="louzaiBean" class="demo.LouzaiBean"
 init-method="init" destroy-method="destroyMethod">
 <property name="name" value="model" />
</bean>
复制代码

测试⼊⼝:

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context =new
                ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        LouzaiBean modelBean = (ModelBean) context.getBean("modelBean");
        louzaiBean.work();
        ((ClassPathXmlApplicationContext) context).destroy();
    }
}
复制代码

执⾏结果:

  • 1.调⽤构造⽅法:我出⽣了!
  • 2.设置属性:我的名字叫model
  • 3.调⽤BeanNameAware#setBeanName⽅法:我要上学了,起了个学名
  • 4.调⽤BeanFactoryAware#setBeanFactory⽅法:选好学校了
  • 5.BeanPostProcessor.postProcessBeforeInitialization⽅法:到学校报名啦
  • 6.InitializingBean#afterPropertiesSet⽅法:⼊学登记
  • 7.⾃定义init⽅法:努⼒上学ing
  • 8.BeanPostProcessor#postProcessAfterInitialization⽅法:终于毕业,拿到毕业证啦! Bean使⽤中:⼯作,只有对社会没有⽤的⼈才放假。
  • 9.DisposableBean#destroy⽅法:平淡的⼀⽣落幕了
  • 10.⾃定义destroy⽅法:睡了,别想叫醒我

这个流程⾮常清晰,Bean ⽣命周期流程图能完全对应起来。

2.4 扩展⽅法

我们发现,整个⽣命周期有很多扩展过程,⼤致可以分为 4 类:

  • Aware 接⼝:让 Bean 能拿到容器的⼀些资源,例如 BeanNameAware 的 setBeanName(), BeanFactoryAware 的 setBeanFactory()
  • 后处理器:进⾏⼀些前置和后置的处理,例如 BeanPostProcessor 的 postProcessBeforeInitialization() 和 postProcessAfterInitialization()
  • ⽣命周期接⼝:定义初始化⽅法和销毁⽅法的,例如 InitializingBean 的 afterPropertiesSet(),以及 DisposableBean 的 destroy()
  • 配置⽣命周期⽅法:可以通过配置⽂件,⾃定义初始化和销毁⽅法,例如配置⽂件配置的 init() 和 destroyMethod()

三. 源码解读

注意:Spring 的版本是 5.2.15.RELEASE,否则和我的代码不⼀样!!!

上⾯的知识,⽹上其实都有,下⾯才是我们的干货,让你跟着我⾛⼀遍代码流程。

3.1 代码⼊⼝

这⾥需要多跑⼏次,把前⾯的 beanName 跳过去,只看 modelBean。

进⼊ doGetBean(),从 getSingleton() 没有找到对象,进⼊创建 Bean 的逻辑。

3.2 实例化

进⼊ doCreateBean() 后,调⽤ createBeanInstance()。

进⼊ createBeanInstance() 后,调⽤ instantiateBean()。

⾛进示例 LouzaiBean 的⽅法,实例化 LouzaiBean。

3.3 属性赋值

再回到 doCreateBean(),继续往后⾛,进⼊ populateBean()。

这个⽅法⾮常重要,⾥⾯其实就是依赖注⼊的逻辑,不过这个不是我们今天的重点,⼤家如果对依赖注⼊和 循环依赖感兴趣,可以翻阅我之前的⽂章。

进⼊ populateBean() 后,执⾏ applyPropertyValues()

进⼊ applyPropertyValues(),执⾏ bw.setPropertyValues()

进⼊ processLocalProperty(),执⾏ ph.setValue()。

⾛进示例 ModelBean 的⽅法,给 ModelBean 赋值 name。

到这⾥,populateBean() 就执⾏完毕,下⾯开始初始化 Bean。

3.4 初始化

我们继续回到 doCreateBean(),往后执⾏ initializeBean()。

⾛进示例 ModelBean 的⽅法,给 ModelBean 设置 BeanName。

回到 invokeAwareMethods()。

⾛进示例 ModelBean 的⽅法,给 ModelBean 设置 BeanFactory。

第⼀次回到 initializeBean(),执⾏下⾯逻辑。

这⾥需要多循环⼏次,找到 MyBeanPostProcessor 的策略⽅法。

我们⾃⼰定义的后置处理⽅法。

第⼆次回到 initializeBean() ,执⾏下⾯逻辑。

⾛进示例 LouzaiBean 的⽅法,执⾏ afterPropertiesSet()。

返回 invokeInitMethods(),执⾏下⾯逻辑。

进⼊ invokeCustomInitMethod(),执⾏下⾯逻辑。

⾛进示例 ModelBean 的⽅法,执⾏ init()。

第三次回到 initializeBean(),执⾏下⾯逻辑。

我们⾃⼰定义的后置处理⽅法。

到这⾥,初始化的流程全部结束,都是围绕 initializeBean() 展开。

3.4 销毁

当 mdoelBean ⽣成后,后⾯开始执⾏销毁操作,整个流程就⽐较简单。

⾛进示例 ModelBean 的⽅法,执⾏ destroy()。

回到 destroy(),执⾏下⾯逻辑。

⾛进示例 ModelBean 的⽅法,执⾏ destroyMethod()。

到这⾥,所有的流程全部结束,⽂章详细描述所有的代码逻辑流转,你可以完全根据上⾯的逻辑,⾃⼰ debug ⼀ 遍,相信印象会更加深刻。

四. 都要总结哦哦哦哦

我们再回顾⼀下⼏个重要的⽅法:

  • doCreateBean():这个是⼊⼝;
  • createBeanInstance():⽤来初始化 Bean,⾥⾯会调⽤对象的构造⽅法;
  • populateBean():属性对象的依赖注⼊,以及成员变量初始化;
  • initializeBean():⾥⾯有 4 个⽅法,
    • 先执⾏ aware 的 BeanNameAware、BeanFactoryAware 接⼝;
    • 再执⾏ BeanPostProcessor 前置接⼝;
    • 然后执⾏ InitializingBean 接⼝,以及配置的 init();
    • 最后执⾏ BeanPostProcessor 的后置接⼝。
  • destory():先执⾏ DisposableBean 接⼝,再执⾏配置的 destroyMethod()。

对于 populateBean(),⾥⾯的核⼼其实是对象的依赖注⼊,这⾥也是常考的知识点,⽐如循环依赖等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值