Springframework-ioc学习(四)之Bean生命周期
在面试的时候,稍微高级一点的面试官,经常会问你对框架的源码掌握程度,而大部分会问你Spring,而关于Spring的问题,大多数会问到Spring中IOC容器管理Bean的生命周期。如果没有仔细阅读过Spring源码的同学是很难讲这个问题彻底说清楚的,如果只是从一些论坛看过类似的文章虽然有短期效果流程能说出来,但其实并没有掌握,因为其内心还没有一个直线能把断断续续的知识点给串联起来,所以很容易忘记。为了讲清楚这部分内容,小编在前3篇文章中已经做了大量的铺垫工作。
第一篇我们讲了xml配置文件是如何被Spring给读取成Java对象也就是解析XML为Document Springframework学习(一)之Xml配置文件加载
第二篇我们讲了Document是如何被Spring的解析器解析成Bean的元数据BeanDefinition Springframework学习(二)之BeanDefinition注册
第三篇我们又讲了Spring是如何给我们开发者提供切入点去最后调整读取到的BeanDefinition Springframework-ioc学习(三)之最后修改BeanDefinition的机会
那么这篇我们就要开始讲BeanDefinition是如何被转换成Bean对象及Bean对象的生命周期。
注意
感兴趣的同学,在看这篇文章的时候,建议结合源码来看,一步一步点进去看看,思考思考。
注意小编图中的注释,有些注释小编是写在图中截图分享的。
文章目录
BeanFactory是如何把BeanDefinition转换成Bean对象
属性注入,构造注入,set注入,参数注入
Bean对象的生命周期
Bean的生命周期这是一个比较形象的描述,其实①主要就是讲Bean从创建到销毁这之间的过程。②其次在Bean从创建到销毁的过程之间会穿插Spring提供给我们供我们实现接口的类的使用讲解,在说白点就是说: Spring在Bean创建的前后给我们开发者去操作的机会,而需要我们继承某些类才能实现这些功能,我们要知道是那些类。如果对以上两点你都清楚了,那么无论是谁让你在讲Bean的生命周期你就可以说是完全掌握了
一.BeanFactory是如何把BeanDefinition转换成Bean对象
前面我们说了BeanDefinition是都保存在DefaultListableBeanFactory类的beanDefinitionMap方法中的。那么我们就应该知道如果要转换bean肯定要
从这个集合中去读取BeanDefinition来进行处理。
我们看下获取Bean的方法。Bean有单例模式和原型模式。单例模式是随着Spring上下文加载完成就已经转换完成的被放在DefaultSingletonBeanRegistry的singletonObjects集合中。
而原型模式是每次加载的时候都会重新去创建一个。他俩的核心实现其实是差不多的,只不过单例是一次加载完成就放到缓存中,而原型是没有使用缓存,而是每次都去创建。为了方便我们深入研究
我们把Bean设置为原型模式和懒加载,为了方便小编第一次就进去到getBean方法里面。
开始进入
其实无论是下面那个方法,调用顺序最后都是这样调用的doGetBean()
①AbstractBeanFactory.doGetBean()
② AbstractAutowireCapableBeanFactory.createBean()
③ AbstractAutowireCapableBeanFactory.doCreateBean()
④ AbstractAutowireCapableBeanFactory.populateBean()
其中123都是实例化Bean而并不会注入其依赖的Bean,(但是排除,使用构造注入的情况)而4才真正想
这个实例中去注入依赖。同时注入通过配置文件读取的配置比如下图。
下面跟着小编的步骤来探索一下。
进入doCreateBean方法(看下图注释)
populateBean实现了注入的功能,可以从ioc中获取自己需要的依赖并注入,同时可以从配置文件中拿到你的依赖的值。
initalizeBean这个方法中是调用InitializingBean的afterPropertiesSet完成用户定义的初始化方法,但是注意初始化方法Spring中有两个
第一个就是实现InitializingBean的afterPropertiesSet,接口
第二个是xml中配置init-method。判断逻辑是先判断是否实现InitializingBean接口,其次判断init-method。如果都有都执行。
,并在前后留下了接口,供开发者对Bean做修改。
到这里当Bean的依赖都注入成功,可以返回getBean了。
二.Bean对象的生命周期
其实上面就已经把Bean的生命周期说了一大半了,除了destroy没有说,其他都讲了。下面我们专门说Bean的销毁方法
destroyBeans中有我们可以学习的东西,看完之后肯定GET到一个点!
首先小编先提一个问题!
小编想问,如果你写的程序正在运行,此时你把idea突然关了,或者是ctrl+z终止了程序,此时怎么去执行销毁呢?
好了本来小编想举几个例子,github,svn等等的钩子程序,但是篇幅太长了,就不扯了。直接上代码。
这段代码在运行时候并不会立即打印,而是在小编点击关闭程序的时候才会执行。其实就是一个hook钩子程序
现在我们在Spring的源码中在找找Spring是
正常情况和非正常情况如何销毁Bean的呢?
正常情况
调用上图步骤13
调用流程图
看到这里我们就清楚@PreDestroy 和DisposableBean接口和xml中destroy-method用户配置的销毁方法的执行顺序了。顺便在这里提一下@PostConstruct和InitializingBean接口和xml中init-method的顺序也是一样的。都是先执行注解的@PreDestroy和@PostConstruct,然后接口DisposableBean/InitializingBean,最后才是xml中用户自己配置的。
非正常情况
非正常情况其实和正常情况的调用流程一样,只是触发的时间点不一样。非正常情况是在ctrl+z或者程序异常退出的时候去执行的。使用的技术就是上面我们演示的hook钩子程序。
我们看AbstractApplicationContext中有一个钩子线程,并提供了一个注册钩子程序的方法registerShutdownHook。说到这里相信大家都明白了吧。
文章来源: springlearn.blog.csdn.net,作者:西魏陶渊明,版权归原作者所有,如需转载,请联系作者。
原文链接:springlearn.blog.csdn.net/article/details/81448120
- 点赞
- 收藏
- 关注作者
评论(0)