首页 > 数据库 > 数据库开发技术 > 复盘女朋友面试4个月的Spring面试题

继续,第四波女朋友面试 4 个月的面试题复盘,这次是关于 Spring 的题目。
Spring 是 Java web 开发接触最多的一个框架,基本上每天都会打交道。
直接上题目。Spring 框架虽然有很多组件,但是面试题目还是比较少的,因为他的核心思想比较集中。还是老套路,高频的面试题已经标星,有面试需要的同学可以先点星星收藏起来。
Spring 的源码非常深,Spring 框架使用了各种设计模式,因此阅读 Spring 的源码比一些国产框架源码会吃力一些,但是这也阻挡不了我们了解 Spring 的原理之路,只要我们平时对 Spring 的原理有一定了解,我们也可以讲清楚常见的面试题目。
下面开始进入面试题的复盘。
这种开放性问题,没有标准的答案,我们不要等面试官问完就回答,我们可以先思考 2 秒,脑袋里将 Spring 进行总结一下。我们按照金字塔原理的方式回答,记住一定要先说重点。
1、Spring 通过 Ioc 和 Di 技术为 Bean 提供了生命周期管理能力,帮助程序员创建 bean 和管理 bean 的关系
2、Spring 提供了面向切面编程 Aop 的编程方式,可以帮助程序员快速集成通用的非业务功能,比如内置的事务功能就是通过 aop 实现的。
3、Spring 框架提供了非常多的扩展点,帮助程序员快速开发和集成第三方组件,比如 bean 的处理器BeanPostProcessor,全局异常处理ControllerAdvice切面等。
有些面试官可能会根据你说的发散的问,所以你回答的点最好都是自己比较熟悉的点。
如果了解 Spring 创建 Bean 的过程,那么这个题目回答起来就没问题。
先说核心重点
再详细说明
首先 bean 的出生就是 Spring 先拿到 bean 的配方BeanDefinition信息,然后通过反射技术势力化一个 bean 对象出来。
这个时候 bean 只是创建了实例,他的属性都是默认值,没有进行用户定制化的属性填充,所以第二步是属性填充。
属性填充之后,Spring 为了给用户一些定制化 bean 的机会,给每个 bean 留下了一些初始化的接口。
aware 感知 Spring 框架 bean 的能力
bean 的后置处理器,初始化前回调函数org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
invokeInitMethods 初始化方法回调
InitializingBean.afterPropertiesSet
invokeCustomInitMethod 包含:PostConstruct 注解
bean 的后置处理器,初始化后回调函数org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
初始化完成之后 Bean 就可以被业务程序使用了,直到程序销毁的时候,bean 也会随之销毁。
Spring 解决循环依赖使用到了三个 map 作为三级缓存,分别存储不同状态的 bean。
/** 一级缓存 存储可以直接使用的bean **/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 二级缓存 存储bean工厂 可以延迟调用实例化 使用的时候才调用工厂方法获取对象 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** 存储不完整对象 不能直接用的 循环依赖时,某些依赖的属性没有设置,这个时候bean就是不完整对象 */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
总结一下,为什么使用三级缓存?
1、singletonObjects 这个缓存是存储完整的对象,可以直接使用的。
2、singletonFactories 这个缓存是为了延迟初始化,是解决循环依赖的关键,存在循环依赖注入时,可能注入的对象需要被代理,这个工厂类来延迟实例化一个代理类。
3、earlySingletonObjects 这个缓存是为了在 A 注入 B,而 B 又注入 A 这个阶段,A 是一个半成品,需要用来存储 A 这种半成品 bean 的状态。需要等待 A 将 B 注入之后,这个缓存就要移除。
4、singletonFactories 和 earlySingletonObjects 都是存储对象的中间状态,依赖它们保证最终注入的对象是完整的,依赖注入完成后会被清除。
Spring aop 是对动态代理技术的封装组件,帮助开发人员使用 aop 实现可插拔的切面功能。
我们可以分三个阶段和面试官说明。
第一阶段 解析程序中定义的切面
这个阶段是解析 aop 注解或者标签的过程,比如 Aspect 标识的类,解析得到 aop 定义的基础 beanAspectJPointcutAdvisor,Advice
第二阶段 查找方法的切面和通知,构建通知
对于需要被切面拦截的 bean,在 bean 实例化之后,开始判断是否要创建代理对象,通过 jdk 或者 cglib,同时构建了通知链数组,并缓存起来。
使用方法对象和方法 hashCode 作为 key
private final Method method;
private final int hashCode;
第三阶段 调用通知链路,执行切面的逻辑。
如果是 jdk 动态代理调用目标方法会触发
org.springframework.aop.framework.JdkDynamicAopProxy#invoke方法
如果是 cglib,调用目标方法会触发 CglibAopProxy 中
org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept方法
其实自动装配是 Springboot 借助 Spring 提供导入 bean 到 Spring 容器的一些机制来实现的。
Spring 提供了@Import,ImportSelector,DeferredImportSelector,ImportBeanDefinitionRegistrar等方式导入 bean 到 Spring 容器中,
同时利用 spring spi 技术,查找配置在spring.factories文件里的自动配置类,这样我们只要按照 SpringBoot 定义规范编写需要自动装配的类就可以实现自动装配了。
Spring 和 Springboot 的题目想回答的时候更加有自信心,对于 ioc,aop 以及他们的扩展点的原理一定要比较清晰,Spring 其他能力都是在这两个核心能力上构建的。
原文作者:服务端技术栈;如有侵权,请联系管理员删除。