第一,这绝对是一个面试高频题。
比第一还重要的第二,这绝对是一个让人爱恨交加的面试题。为什么这么说?我觉得可以从三个方面来说:
先说会不会。看过源码的人,这个不难;没看过源码的人,无论是学、硬背、还是说,绝对是一个坎。
再说考察点。这个问题还是比较开放的。可以用三五句话讲出来,也可以揪着面试官聊半个小时。
最后说效果。说的不好,绝对“狠减分”;说的好了,也绝对“狠加分”。
所以说,遇到这个问题,要么颤抖着死去,要么就需要你有强大的忍住不笑了的能力(这个梗可懂)。
好吧好吧,既然都这么“硬核”了,我们没有理由不拿下。
接下来我尝试站在面试官的角度来分析,“他们”想考察的知识点,摸清了套路,再设法一点点的去“喂饱”面试官。
第一层:简单回答问题
面试官心里分析:
作为面试官,我提这个问题,想知道你是否有看源码的习惯或者说经历。通过你的回答,我能初步判断出,你平时是满足于“CRUD”完成需求?还是有好奇心去寻找底层是如何实现的?进而我也就能预判,如果招你进来,是一个偏执行性的人,还是能在团队中承担更多的责任,能主动探究和发现问题。
其实这相当于面试官给我们画好的圈子,只要我们提出几个关键点,即可证明我们看过。
非主流标准答案:
part1.
在真正开始bean的生命周期之前,会读取资源文件,生成BeanDefinition对象。BeanDefinition是bean的前生,bean是BeanDefinition的今世。BeanDefinition除了像Class那样描述了属性方法之类的外,还描述bean的其他特性,比如,是否单例,依赖关系等
part2.
在整个生命周期中,主要就是两件事,bean的创建和赋值以及依赖关系的注入;通过各个扩展点丰富bean的能力,比如BeanFactoryPostProcessor、BeanPostProcessor等。
第二层:展露亮点
面试官心里分析:
仅仅达到目标我们就满足了吗?当然不能,我们追求的,是卓越!如果我们能借助一个类似流程图之类的框架,把bean生命周期在最短的时间内,清晰,简明的描述出来,这就是让面试官眼前一亮的亮点。我会觉得你,除了好奇心和自驱力外,理解和总结能力也不错,以后我们称为同事沟通时,不会让我觉得经常鸡同鸭讲(别告诉我你没遇到过这种人,给他把方案讲三两遍,一直在点头,等做出来的活发现还是南辕北辙,这绝对不是笑话)。
非主流标准答案:
part1.
bean的生命周期,主要经历4个阶段,4类扩展。分别结合两张图来说明,先来看下4个阶段:
说明:怎么理解这个过程呢?
类比我们自己构造一个对象,也是先调用构造函数创建,然后通过setter为属性赋值。分别对应了上图中的【实例化】和【为Bean属性赋值。
这里提了初始化环节,该环节对应执行的,是我们在定义bean(比如xml配置,比如注解中配置)时,配置的init方法。
最后一个注销,就更好理解了,在Java出现之前的C时代,是需要程序员自己管理内存的,那么在分配内存创建对象后,是需要自己注销对象释放内存的。那么既然已经在Java里了为什么还要明确的有这个环节呢?我理解,作为框架,首先不能完全依赖GC来回收对象,这样太被动了;另外,我都是框架了,框架二字意味着什么?超强的整合能力!翻译成人话就是,你想要的都在这,你想做什么我都给你留了“后门”(接口)。,那当你想在这个环节搞点什么事情的时候,却发现我无能为力,岂不是尬了?
part2.
接下来再来看4类扩展。所谓扩展,首先我们简单的理解下,无非就是提供了一系列的接口,你只要实现这些接口,就能在整个生命周期的某一个节点,执行你实现的方法逻辑,在这个方法里呢,可以拿到xxx对象(比如ApplicationContext,比如BeanDefinition,比如Bean等等);然后对这些对象做点什么。还是来看下图:
请看上图,一个色系代表一类接口。
BeanFactoryPostProcessor接口,实现该接口可以拿到BeanDefinition,可以做修改。
BeanPostProcessor接口,上图中的InstantiationAwareBeanPostProcessor是其子接口,所以都归为一类,都是和创建bean相关的。
xxxAware接口,比如BeanNameAware,BeanFactoryAware,ApplicationContextAware,拿ApplicationContextAware来说,可以获取当前上下文,然后进而拿到bean的实例,进行处理。
xxxBean接口,有三个典型应用:
FactoryBean:能生产bean的工厂。
InitializingBean:初始化bean时候可进行扩展
DiposibleBean:注销bean时候可进行的扩展
第三层:释放个人魅力
面试官心里分析:
在讲清流程的基础上,如果你还能说一说框架在现实中的应用就更上一层楼了,我会认为你在工作中遇到问题时,工具箱里可选的工具更多。这无论从哪个角度来看,都能为团队带来正向的收益。
非主流标准答案:
BeanFactoryPostProcessor接口应用:
mybatis,就是实现该接口的子接口,来通过mapper接口和xml中的sql,生成对应的类的BeanDefinition,这样在使用时,就不用自己在写连接数据库,创建Session,执行查询等等逻辑了。
在spring-boot中,入口方法在标注了@Configuration注解的类中,那这个方法是如何注入到spring中的呢?扫描标注该注解的逻辑,就是写在实现了BeanFactoryPostProcessor接口的子接口的实例里。
还有直接实现BeanFactoryPostProcessor接口的,比如我们定义的DataSource中的占位符,替换成实际的值。
BeanPostProcessor接口的应用:
AOP中需要在创建实例前判断是否需要创建代理对象,相当于是阻断了实例的创建。就是在实现InstantiationAwareBeanPostProcessor接口的实例中实现的,执行的是xxxBefore()方法
我们常用@AutoAware注解,引入一个bean,其依赖注入就是在InstantiationAwareBeanPostProcessor.xxxPropertyValues()方法中实现的。
其他的,暂时不在这里列出,既然你看到了这篇文章,那么也参与进来,我们一起补全。
如果看的还算过瘾,关注这个公号,我们接着聊。