前言
大家在面试的时候不同程度会被问到JVM的垃圾回收,看面试官水平,有些就背个书就行,比如GC的工作原理,有哪些GC算法和回收器,分别优点和缺点等等,有些面试官估计自己也就背书水平,都没个追问;有些面试官就能追问,一追问就歇菜,比如低延迟的垃圾回收器有哪些以及其原理,跨代引用及解决方案,三色标记及漏标问题处理,等等。
还是那句话,虽然都是些理论的问题,但是在实际开发过程中真的能遇到这些问题来解决实际问题,所以多多了解JVM的实现原理总没有错,既能抗极限面试,又能在适时的时候帮忙解决实际问题,得到领导和同事的赞赏,何乐不为?
下面进入正题,先来个开胃菜,热热身。GC的工作原理就不说了,要准备面试的同学必须倒背如流,不然面试官要说出门右转了…
这里分享一个阅读源码的小技巧:捉大放小,连蒙带猜!
8字真言,我们在阅读源码过程中,因为你要知道,每一个被开源出来的优秀框架,其源码的体系都是极其庞大复杂的,我们不能面面俱到,所以在看源码过程中一定不能被细枝末节缠住,一定要先理清楚整个框架的一个大致思想和大致的框架体系,再去搞那些细枝末节,其效率会好很多,其次在看源码过程中,我们一定要大胆的去想,去猜测,如果这个功能让你自己去写,你会怎么实现!
我们今天学习SpringBean的生命周期也是按照这个8字真言去学习,通过我们之前所学,Spring大致有以下的功能:
我们从平常的使用中,至少可以得知以上的三点,如果让你自己去实现,必会如何实现呢?
Map
容器是最合适的!jdk
或者cglib
的代理然后再保存进容器里面!于是乎,我们自己实现了一个Spring管理一个Bean的所有过程,画个图,他大概长这样!
自己实现看起来,整个流程就很清晰,扫描、创建、注入、代理、保存一应俱全,但是Spring的实现方式远比我们自己实现的要复杂的多得多!
Spring作者希望,Spring再着手管理一个Bean的时候,它希望能够让Spring的使用者能够插手,Spring把一个类对象变成一个Java Object的每一步,怎么理解呢?
比如我们买了一栋新房子,这个房子需要取装修,你自己去装修诚然不够专业,不能够面面俱到,所以是我们就找了一个装修公司帮助我们装修新房,于是装修公司就开始预先画好的图纸进行装修,但是在装修的过程中,你为了让自己的新家更加温馨,你想挂一些壁画在墙上,但是图纸上却没有!于是你就找装修公司,要求装修公司在新家的墙上挂上一些壁画!装修公司在接受到你的请求之后,就吩咐装修的工人在图纸之外去给你在墙上挂上壁画之后,然后再接着装修!
上面这个小故事有 这样几个角色,我们把它和Spring对照起来!
上面的小故事,大致可以描述Spring生命周期的核心思想!Spring再对一个Class文件实例化成具体的Spring Bean的时候,它提供了各种接口,由我们自己实现!然后再实例化过程中,不同的时机,去调用不同的接口!从而完成Spring的整个生命周期的创建!
Spring的生命周期大致分为以下部分!
扫描项目,将项目指定目录下的Class文件转换为Class对象!
读取Class对象属性包装为BeanDefinition
,然后保存再一个Map中!(不难理解,他是为了后续创建或者读取这个类的信息更加方便取而创立的)
将全部的类转化为 BeanDefinition
并保存之后,开始调用第一个回调接口BeanFactoryPostProcessor#postProcessBeanFactory()
!
BeanDefinition
之后调用的,我们可以通过回调的方法获取所有的BeanDefinition
,而后续的所有对Class的操作都是基于BeanDefinition
操作的,所以,我们可以通过修改它,来改变后续的流程!先从当前的容器对象取当前要创建的对象,当取出来的对象为null时开始着手创建对象!
做一系列的验证,比如验证这个类是否被排除、是否正在创建中、是否有依赖Bean【@DependsOn】注解、是否时单例等等!
验证通过之后,开始通过反射创建这个对象!
合并BeanDefinition
,这里涉及到Spring之前版本使用的父子容器的概念,属于另外一个知识点不做讲解!
判断当前对象是不是单例、是不是支持循环引用、是不是正在创建等!
执行第二个接口回调InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation()
方法!
执行第三个接口回调InstantiationAwareBeanPostProcessor#postProcessProperties()
方法!
填充属性到对象!
调用第四个回调接口BeanNameAware#setBeanName()
方法!
调用第五个回调接口BeanClassLoaderAware#setBeanClassLoader()
BeanNameAware
之后,他的功能是传入bean的类加载器;调用第六个回调接口BeanFactoryAware#setBeanFactory()
!
BeanClassLoaderAware
之后,用于设置beanFactory!调用第七个回调接口BeanPostProcessor#postProcessBeforeInitialization()
方法
Aware
之后,初始化方法之前!传入当前实例化好的对象和beanName,再初始化前做修改!回调第八个比较重要的生命周期的初始化方法,它可以是一个InitializingBean
接口的bean,也可以是xml中配置的类,也可以是被加了@PostConstruct
注解的方法!
回调第九个回调接口 BeanPostProcessor#postProcessAfterInitialization()
方法!
注册销毁方法,以便Spring容器销毁的时候进行方法的销毁!
整体的方法流程示例图如下:
这不止是一份面试清单,更是一种”被期望的责任“,因为有无数个待面试者,希望从这篇文章中,找出通往期望公司的”钥匙“,所以上面每道选题都是结合我自身的经验于千万个面试题中经过艰辛的两周,一个题一个题筛选出来再次对好答案和格式做出来的,面试的答案也是再三斟酌,深怕误人子弟是小,影响他人仕途才是大过,也希望您能把这篇文章分享给更多的朋友,让他帮助更多的人,帮助他人,快乐自己,最后,感谢您的阅读。
资料领取方式:戳这里免费获取
希望您能把这篇文章分享给更多的朋友,让他帮助更多的人,帮助他人,快乐自己,最后,感谢您的阅读。
资料领取方式:戳这里免费获取
由于细节内容实在太多啦,在这里我花了两周的时间把这些答案整理成一份文档了,在这里只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!