大家好,我是楼仔!,Spring Bean 的生命周期,面试时非常容易问,这不,前段时间就有个粉丝去字节面试,因为不会回答这个问题,一面都没有过。,如果只讲基础知识,感觉和网上大多数文章没有区别,但是我又想写得稍微深入一点。,考虑很多同学不喜欢看源码,我就把文章分为 2 大部分,前面是基础知识,主要方便大家面试和学习,后面是源码部分,对源码感兴趣的同学可以继续往后面看。,
,IoC,控制反转,想必大家都知道,所谓的控制反转,就是把 new 对象的权利交给容器,所有的对象都被容器控制,这就叫所谓的控制反转。,IoC 很好地体现了面向对象设计法则之一 —— 好莱坞法则:“别找我们,我们找你”,即由 IoC 容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。,理解好 IoC 的关键是要明确 “谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”。,
,传统 Java SE 程序设计,我们直接在对象内部通过 new 进行创建对象,是程序主动去创建依赖对象。而 IoC 是由专门一个容器来创建这些对象,即由 IoC 容器来控制对象的创建。,为何是反转,哪些方面反转了?,有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转,而反转则是由容器来帮忙创建及注入依赖对象。,对 Prototype Bean 来说,当用户 getBean 获得 Prototype Bean 的实例后,IOC 容器就不再对当前实例进行管理,而是把管理权交由用户,此后再 getBean 生成的是新的实例。,所以我们描述 Bean 的生命周期,都是指的 Singleton Bean。,
,Bean 生命周期过程:,整个执行流程稍微有些抽象,下面我们通过代码,来演示执行流程。,创建一个 LouzaiBean。,自定义一个后处理器 MyBeanPostProcessor。,applicationContext.xml 配置文件(部分)。,测试入口:,执行结果:,这个流程非常清晰,Bean 生命周期流程图能完全对应起来。,我们发现,整个生命周期有很多扩展过程,大致可以分为 4 类:,注意:Spring 的版本是 5.2.15.RELEASE,否则和我的代码不一样!!!,上面的知识,网上其实都有,下面才是我们的重头戏,让你跟着我走一遍代码流程。,
,
,这里需要多跑几次,把前面的 beanName 跳过去,只看 louzaiBean。,
,
,进入 doGetBean(),从 getSingleton() 没有找到对象,进入创建 Bean 的逻辑。,
,
,进入 doCreateBean() 后,调用 createBeanInstance()。,
,进入 createBeanInstance() 后,调用 instantiateBean()。,
,
,
,
,
,走进示例 LouzaiBean 的方法,实例化 LouzaiBean。,
,再回到 doCreateBean(),继续往后走,进入 populateBean()。,这个方法非常重要,里面其实就是依赖注入的逻辑,不过这个不是我们今天的重点,大家如果对依赖注入和循环依赖感兴趣,可以翻阅我之前的文章。,
,进入 populateBean() 后,执行 applyPropertyValues(),
,进入 applyPropertyValues(),执行 bw.setPropertyValues(),
,
,
,
,进入 processLocalProperty(),执行 ph.setValue()。,
,
,
,走进示例 LouzaiBean 的方法,给 LouzaiBean 赋值 name。,
,到这里,populateBean() 就执行完毕,下面开始初始化 Bean。,我们继续回到 doCreateBean(),往后执行 initializeBean()。,
,
,
,走进示例 LouzaiBean 的方法,给 LouzaiBean 设置 BeanName。,
,回到 invokeAwareMethods()。,
,走进示例 LouzaiBean 的方法,给 LouzaiBean 设置 BeanFactory。,
,第一次回到 initializeBean(),执行下面逻辑。,
,这里需要多循环几次,找到 MyBeanPostProcessor 的策略方法。,
,我们自己定义的后置处理方法。,
,第二次回到 initializeBean(),执行下面逻辑。,
,
,走进示例 LouzaiBean 的方法,执行 afterPropertiesSet()。,
,返回 invokeInitMethods(),执行下面逻辑。,
,进入 invokeCustomInitMethod(),执行下面逻辑。,
,走进示例 LouzaiBean 的方法,执行 init()。,
,第三次回到 initializeBean(),执行下面逻辑。,
,
,我们自己定义的后置处理方法。,
,到这里,初始化的流程全部结束,都是围绕 initializeBean() 展开。,2.4 销毁,当 louzaiBean 生成后,后面开始执行销毁操作,整个流程就比较简单。,
,
,
,
,
,
,
,
,
,
,走进示例 LouzaiBean 的方法,执行 destroy()。,
,回到 destroy(),执行下面逻辑。,
,
,
,走进示例 LouzaiBean 的方法,执行 destroyMethod()。,
,到这里,所有的流程全部结束,文章详细描述所有的代码逻辑流转,你可以完全根据上面的逻辑,自己 debug 一遍。,我们再回顾一下几个重要的方法:,先执行 aware 的 BeanNameAware、BeanFactoryAware 接口;,再执行 BeanPostProcessor 前置接口;,然后执行 InitializingBean 接口,以及配置的 init();,最后执行 BeanPostProcessor 的后置接口。,destory():先执行 DisposableBean 接口,再执行配置的 destroyMethod()。,对于 populateBean(),里面的核心其实是对象的依赖注入,这里也是常考的知识点,比如循环依赖,大家如果对这块也感兴趣,可以私下和我交流。,今天的源码解析就到这,Spring 相关的源码,还有哪些是大家想学习的呢,可以给楼仔留言。,这篇文章肝了我一个星期,原创不易,大家的点赞和分享,是我继续创作的最大动力!,三分恶的《Spring Bean生命周期,好像人的一生。。》:https://juejin.cn/post/7075168883744718856
© 版权声明
文章版权归作者所有,未经允许请勿转载。