Spring相关面试题

Posted lisin-lee-cooper

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring相关面试题相关的知识,希望对你有一定的参考价值。

一.IOC面试整理

1.1什么是Spring

SpringFramework 是一个开源的、松耦合的、分层的、可配置的一站式企业级 Java 开发框架,它的核心是 IOC 与 AOP ,它可以更容易的构建出企业级 Java 应用,并且它可以根据应用开发的组件需要,整合对应的技术。

1.2为什么使用Spring


IOC:组件之间的解耦(由强依赖降为弱依赖)
AOP:切面编程可以将应用业务做统一或特定的功能增强,能实现应用业务与增强逻辑的解耦
容器与事件:管理应用中使用的组件 Bean、托管 Bean 的生命周期、事件与监听器的驱动机制
Web、事务控制、测试、与其他技术的整合

2.1 IOC是什么

IOC 控制反转是一种思想,它的核心是将控制权转交出去。利用 IOC 思想,可以实现组件之间的解耦。IOC 的实现方式通常有依赖注入和依赖查找。

2.2 为什么使用IOC

解耦
解决对象间的依赖关系
托管对象的大部分生命周期过程,应用程序仅关心使用过程

2.3 Spring中的自动注入模式

byType :根据类型注入
byName :根据组件的 name 注入
byConstructor :根据构造器注入
autodetect :通过类的内省机制决定使用哪种方式注入
顺序:byConstructor → byType
no :不自动注入(默认)

2.4 beanFactory与ApplicationContext区别

ApplicationContext是BeanFactory的字接口,扩张了以下功能:

AOP 的支持( AnnotationAwareAspectJAutoProxyCreator 作用于 bean 的初始化之后 )
配置元信息( BeanDefinition 、Environment 、注解等 )
资源管理( Resource 抽象 )
事件驱动机制( ApplicationEvent 、ApplicationListener )
消息与国际化( LocaleResolver )
Environment 抽象

2.5 BeanFactory 与 FactoryBean的区别

BeanFactory :
SpringFramework 中实现 IOC 的最底层容器,
它是最顶级的接口,也就是最顶层的容器实现;
FactoryBean :
创建对象的工厂 Bean ,可以使用它来直接创建一些初始化流程比较复杂的对象。

2.6 后置处理器对比

1.BeanDefinitionRegistryPostProcessor:处理BeanDefinition 、.class 文件等,配置文件、配置类已解析完毕并注册进 BeanFactory ,但还没有被 BeanFactoryPostProcessor 处理,向 BeanFactory 中注册新的BeanDefinition;

2.BeanFactoryPostProcessor:处理BeanDefinition,BeanDefinition 解析完毕并注册进 BeanFactory 之后执行,给 BeanDefinition 中增删属性、移除 BeanDefinition 等;

3.BeanPostProcessor:处理bean 实例,bean 的初始化阶段前后执行,给 bean 的属性赋值、创建代理对象等;

2.7 bean的类型(6种)

singleton 一个 IOC 容器中只有一个【默认值】
prototype 每次获取创建一个
request 一次请求创建一个(仅 Web 应用可用)
session 一个会话创建一个(仅 Web 应用可用)
application 一个 Web 应用创建一个(仅 Web 应用可用)
websocket 一个 WebSocket 会话创建一个(仅 Web 应用可用)

2.8 bean的实例化方式(5种)

1.直接通过 / @Bean / @Component 的方式注册 Bean 后实例化
2.借助 FactoryBean 实例化 bean
3.使用静态工厂方法( factory-method )实例化 bean
4.使用实例工厂方法( factory-bean + factory-method )实例化 bean
5.借助 InstantiationAwareBeanPostProcessor 实例化 bean (该法比较特殊,它实际上是拦截原有 bean 的创建流程而已)

3.Bean的生命周期

3.1.构建BeanDefinition
1.加载 xml 配置文件: 发生在基于 xml 配置文件的 ApplicationContext 中 refresh 方法的 BeanFactory 初始化阶段,此时 BeanFactory 刚刚构建完成,它会借助 XmlBeanDefinitionReader 来加载 xml 配置文件,并使用 DefaultBeanDefinitionDocumentReader 解析 xml 配置文件,封装声明的 标签内容;
2.解析注解配置类:ApplicationContext 中 refresh 方法的 BeanDefinitionRegistryPostProcessor 执行阶段;
3.编程式构造 BeanDefinition :发生在 ApplicationContext 中 refresh 方法的 BeanDefinitionRegistryPostProcessor 执行阶段;
4.BeanDefinition 的后置处理:

3.2Bean的实例化
1.bean 的实例化​
2.属性赋值 + 依赖注入​
3.bean 的初始化生命周期回调​
4.bean 实例的销毁

4.SPI机制

是通过一种“服务寻找”的机制,动态的加载接口 / 抽象类对应的具体实现类,它把接口具体实现类的定义和声明权交给了外部化的配置文件中。

jdk 的 SPI 是需要遵循规范的:所有定义的 SPI 文件都必须放在工程的 META-INF/services 目录下,且文件名必须命名为接口 / 抽象类的全限定名,文件内容为接口 / 抽象类的具体实现类的全限定名,如果出现多个具体实现类,则每行声明一个类的全限定名,没有分隔符。

二 AOP面试整理

1.1什么是AOP

AOP 面向切面编程,全称 Aspect Oriented Programming ,它是 OOP 的补充。OOP 关注的核心是对象,AOP 的核心是切面(Aspect)。AOP 可以在不修改功能代码本身的前提下,使用运行时动态代理的技术对已有代码逻辑增强。AOP 可以实现组件化、可插拔式的功能扩展,通过简单配置即可将功能增强到指定的切入点。

1.2AOP术语

Target 目标对象:被代理的原始对象
Proxy 代理对象:目标对象被织入通知后的产物就是代理对象
JoinPoint 连接点:目标对象的所属类中,定义的所有方法均为连接点
Pointcut 切入点:被切面拦截 / 增强的连接点(切入点一定是连接点,连接点不一定是切入点)
Advice 通知:增强的逻辑 / 代码,也即拦截到目标对象的连接点之后要做的事情
Aspect 切面:切入点 + 通知
Weaving 织入:将通知应用到目标对象,进而生成代理对象的过程动作
Introduction 引介:特殊的通知类型,可以在不修改原有类的代码的前提下,在运行期为原始类动态添加新的属性 / 方法

1.3 通知类型

1 AspectJ定义的通知类型

Before 前置通知:目标对象的方法调用之前触发
After 后置通知:目标对象的方法调用之后触发
AfterReturning 返回通知:目标对象的方法调用完成,在返回结果值之后触发
AfterThrowing 异常通知:目标对象的方法运行中抛出 / 触发异常后触发
注意一点,AfterReturning 与 AfterThrowing 两者是互斥的!如果方法调用成功无异常,则会有返回值;如果方法抛出了异常,则不会有返回值。
Around 环绕通知:编程式控制目标对象的方法调用。环绕通知是所有通知类型中可操作范围最大的一种,因为它可以直接拿到目标对象,以及要执行的方法,所以环绕通知可以任意的在目标对象的方法调用前后搞事,甚至不调用目标对象的方法

2 AOP联盟定义的通知类型

前置通知 MethodBeforeAdvice
后置通知(返回通知)AfterReturningAdvice
异常通知 ThrowsAdvice
环绕通知 MethodInterceptor
引介通知 IntroductionAdvisor

1.4AOP使用场景

业务日志切面:可以记录业务方法调用的痕迹
事务控制:通过切面可以声明式控制事务
权限校验:执行方法之前先校验当前登录用户是否有权调用
数据缓存:执行方法之前先从缓存中取

1.5 AOP原理

1.AOP的底层设计是由运行时动态代理支撑,在 bean 的初始化流程中,借助 BeanPostProcessor 将原始的目标对象织入通知,生成代理对象。

2.AOP 在底层,借助 AnnotationAwareAspectJAutoProxyCreator 在 bean 的初始化流程,postProcessAfterInitialization 方法中将目标对象包装为代理对象。这里面涉及到几个核心步骤:

2.1检查当前初始化的 bean 是否可以被 AOP 代理(检查是否有匹配的增强器)
2.2如果存在,则根据当前初始化的 bean 所属类有无实现接口,以及 AOP 的全局配置,决定使用哪种代理方案
2.3将目标对象包装为 TargetSource ,并以此为原型生成代理对象

4.代理对象被构造后,执行方法会进入 JdkDynamicAopProxy / CglibAopProxy 中,并构造 ReflectiveMethodInvocation 并依次执行这些织入的通知。执行通知的逻辑是靠一个 currentInterceptorIndex 下标控制,并以此下标为依据顺序执行增强器的通知逻辑。

三.Spring 事务

1.事务四大特性

原子性:一个事务就是一个不可再分解的单位,事务中的操作要么全部做,要么全部不做。原子性强调的是事务的整体
一致性:事务执行后,所有的数据都应该保持一致状态。一致性强调的是数据的完整
隔离性:多个数据库操作并发执行时,一个请求的事务操作不能被其它操作干扰,多个并发事务执行之间要相互隔离。隔离性强调的是并发的隔离
持久性:事务执行完成后,它对数据的影响是永久性的。持久性强调的是操作的结果

2.事务隔离级别

针对数据库的并发操作,可能会出现一些事务的并发问题。事务并发操作中会出现三种问题:

脏读:一个事务读到了另一个事务没有提交的数据
不可重复读:一个事务读到了另一个事务已提交修改的数据
对同一行数据查询两次,结果不一致
幻读:一个事务读到了另一个事务已提交新增的数据
对同一张表查询两次,出现新增的行,导致结果不一致
针对上述三个问题,由此引出了事务的隔离级别:

read uncommitted 读未提交 —— 不解决任何问题
read committed 读已提交 —— 解决脏读
repeatable read 可重复读 —— 解决脏读、不可重复读
serializable 可串行化 —— 解决脏读、不可重复读、幻读
四种隔离级别,自上而下级别逐级增高,但并发性能逐级降低。mysql 中默认的事务隔离级别是 repeatable read ,Oracle 、PostgresSQL 的默认事务隔离级别是 read committed 。

3.事务分传播行为

PROPAGATION_REQUIRED:必需的 如果当前没有事务运行,则会开启一个新的事务;如果当前已经有事务运行,则方法会运行在当前事务中
PROPAGATION_REQUIRES_NEW :新事务 如果当前没有事务运行,则会开启一个新的事务;如果当前已经有事务运行,则会将原事务挂起(暂停),重新开启一个新的事务。当新的事务运行完毕后,再将原来的事务释放
PROPAGATION_SUPPORTS :支持 如果当前有事务运行,则方法会运行在当前事务中;如果当前没有事务运行,则不会创建新的事务(即不运行在事务中)
PROPAGATION_NOT_SUPPORTED :不支持 如果当前有事务运行,则会将该事务挂起(暂停);如果当前没有事务运行,则它也不会运行在事务中
PROPAGATION_MANDATORY :强制 当前方法必须运行在事务中,如果没有事务,则直接抛出异常
PROPAGATION_NEVER :不允许 当前方法不允许运行在事务中,如果当前已经有事务运行,则抛出异常
PROPAGATION_NESTED :嵌套 如果当前没有事务运行,则开启一个新的事务;如果当前已经有事务运行,则会记录一个保存点,并继续运行在当前事务中。如果子事务运行中出现异常,则不会全部回滚,而是回滚到上一个保存点

4.事务监听器

@TransactionalEventListener :
它可以在事务执行的特定阶段触发事件监听。事务监听支持以下 4 种监听时机:

BEFORE_COMMIT :事务提交之前触发监听
AFTER_COMMIT :事务提交之后触发监听
AFTER_ROLLBACK :事务回滚之后触发监听
AFTER_COMPLETION :事务完成之后触发监听(无论提交或回滚均触发)

四.SpringMVC面试整理

1.SpringWebMvc 核心组件

DispatcherServlet :核心的中央处理器,负责接收请求、分发,并给予客户端响应
HandlerMapping :处理器映射器,根据 uri ,去匹配查找能处理的 Handler ,并会将请求涉及到的拦截器,和 Handler 一起封装
HandlerAdapter :处理器适配器,根据 HandlerMapping 找到的 Handler ,适配执行对应的 Handler
ViewResolver :视图解析器,根据 Handler 返回的逻辑视图 / 视图,解析并渲染真正的视图,并传递给 DispatcherServlet 响应客户端
Handler :处理实际请求的处理器

2.工作流程

1、 用户发送请求至前端控制器DispatcherServlet。

2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。

3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。

4、 DispatcherServlet调用HandlerAdapter处理器适配器。

5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。

6、 Controller执行完成返回ModelAndView。

7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。

8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。

9、 ViewReslover解析后返回具体View。

10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。

11、 DispatcherServlet响应用户。

以上是关于Spring相关面试题的主要内容,如果未能解决你的问题,请参考以下文章

Spring相关面试题

Spring相关面试题

每天五个java相关面试题--spring篇

Java SSM框架相关基础面试题整理

springboot+springcloud相关面试题

Java面试题:Spring中如何使用注解来配置Bean?有哪些相关的注解?