前言
共22题。
谈谈你对Spring IOC的理解?
本质上就是控制反转,是一种解耦,就是将对象的控制权由程序员手中反转到Spring手中。
Spring也会自动完成依赖注入以及创建所需的对象。
经常使用并且属性不变的对象放在IOC容器中(controller、service)。
Spring中有哪些依赖注入方式?
主要包括两种方式:构造器依赖注入和Setter方法注入。
你用过哪些Spring注解?(高频)
我们常用的Spring注解主要分为下面几大类:
-
创建对象:
@Component、@Controller、@Service、@Repository; -
依赖注入:
@Autowired、@Qualifier、@Resource; -
配置类:
@Configuration、@Bean; -
其他:声明注解扫描的
@ComponentScan,声明Bean的作用域的@Scope,用于切面编程的@Around,@Pointcut等等。
SpringBean的作用域有几种?
常见的有:
-
单例:对象随
Spring容器创建而创建,跟随Spring容器销毁而销毁,无论获取多少次得到的都是同一个对象,这也是默认作用域。 -
多例:每次获取的时候才会创建,而且每次获取到的都不一样。
还有三种分别是request、session和application。
Spring中的bean线程安全吗?
Spring中的Bean主要分为单例和多例:
-
多例对象每次获取都会创建新实例,也就是说线程之间不存在
Bean共享问题,也就不存在线程安全问题; -
单例对象是所有线程共享一个实例,因此就可能会存在线程安全问题。但是单例对象又分为无状态和有状态,无状态指只查询不会修改,因此不存在线程安全问题,有状态需要进行修改,因此就可能存在线程安全问题,所以只有有状态的单例
Bean才会存在线程安全问题。
有两种方法来处理:
-
将
Bean的作用域由单例改为多例; -
将可变的变量存在
ThreadLocal中, 有线程隔离的特性,每个线程只需要操作自己的,从而解决线程安全问题。
谈谈你对SpringAOP的理解?
AOP,又叫面向切面编程,就是将那些共用的封装起来,然后再动态插入到业务中。可以减少重复代码,降低耦合,并有利于扩展和维护。
AOP基于动态代理,支持JDK和CGLIB的代理方式,并且会根据被代理类是否有接口自动选择最合适的代理方式。
主要使用场景有:事务管理、日志(操作记录)、性能监视、安全检查。
AOP的代理有几种方式?
有两种:
-
JDK动态代理模式:只能对有接口的类进行代理,而且效率较高;
-
CGLIB代理模式:可以对任意的类进行动态代理,但是效率上不如
JDK。
总的来说,如果被代理类有接口,就用JDK;如果没有接口,就用CGLIB。
SpringAOP的通知类型有哪些?
五种类型的通知:
-
前置通知:在某切点之前执行的通知;
-
返回后通知:在某切点正常完成后执行的通知;
-
抛出异常后通知:在某切点抛出异常退出时执行的通知;
-
后置通知:在某切点退出的时候执行的通知(不论是正常返回还是异常退出);
-
环绕通知:包围一个切点的通知(一个可以包含那四个通知)。
了解Spring的事务管理吗?
Spring支持编程式事务和声明式事务。
-
编程式事务:使用
try-catch捕获异常,配合事务的api来手动处理事务问题。这种方式的缺点是代码耦合,复用性低,优点是可以精确控制要增强的代码; -
声明式事务:基于
AOP,将业务方法作为切点,将事务处理方法作为增强,通过动态代理实现事务的管理。它的优点是降低代码耦合,复用性高。目前在企业中基本上都是采用声明式事务的。
Spring事务传播行为有几种?
7种:
-
必须事务:默认必须有事务,有就加入,没有就新建;
-
必须新事务:必须有新事务,有就新建,没有也新建;
-
强制事务:有就加入,没有就抛出异常;
-
强制无事务:有就抛出异常;
-
支持事务:有就加入该事务,没有就继续运行;
-
不支持事务:有就挂起,没有就继续运行;
-
嵌套事务:外层失败内层回滚,内层失败外层正常运行。
Spring中的事务是如何实现的?
Spring事务底层是基于数据库事务和AOP机制的,使用了一个注解@Transactional,如果执行sql没有异常就提交,有异常就回滚。
@Transactional控制事务的原理?
@Transactional注解控制事务原理上是基于AOP来实现的:
-
先从连接池中获取
connection再把事务改成手动提交(mysql事务是自动提交的),获取到的connection会放入到ThreadLocal中; -
整个方法执行完有问题
rollback,没有问题再commit提交(保证这个方法中共用的是同一个connection); -
connection改为自动提交后再还回连接池中,并把ThreadLocal中的connection移除掉。
如果是分布式事务,就会涉及多个数据源,此时不能再用
ThreadLocal,而是要用一个事务调节器:Seata,让Seata管理从多个数据源来的connection。
@Transactional注解有哪些参数?
共有9个参数,分别为:
isolation事务隔离级别,默认为DEFAULTpropagation事务传播机制,默认为REQUIREDreadOnly事务读写性,默认为falsenoRollbackFor一组异常类,遇到时不回滚,默认为{}noRollbackForClassName一组异常类名,遇到时不回滚,默认为{}rollbackFor一组异常类,遇到时回滚,默认为{}rollbackForClassName一组异常类名,遇到时回滚,默认为{}timeout超时时间,以秒为单位value可选的限定描述符,指定使用的事务管理器,默认为“”
Spring中的设计模式有哪些?
-
工厂模式:创建
bean对象; -
单例模式:
bean对象默认都是单例的; -
代理模式:
AOP功能用到了JDK和CGLIB的动态代理方式; -
模板方法模式:用来解决代码重复的问题。比如
RestTemplate; -
观察者模式:
spring的事件监听器ApplicationLisener。
Spring是怎么解决循环依赖的?
循环依赖简单来说就是a依赖b,b依赖a ,a和b之间相互注入,导致它们之间形成了一个闭环,无法继续执行下去的情况。
解决循环依赖利用了三级缓存:
-
一级缓存:放已经初始化完成的实例
-
二级缓存:放未初始化完成的实例
-
三级缓存:放用来创建对象的工厂(
ObjectFactory)
如果加了@Async会报错,因为它也会产生一个对象,所以a或者b上加@Lazy。
SpringBean的生命周期?
主要由五个部分构成:
-
构造Bean对象:相当于
new对象; -
设置Bean属性:给属性赋值;
-
初始化回调:加上
@PostConstruct的方法称为初始化方法,有就执行,没有就不执行; -
Bean调用:进行调用,要用对象的话从
ConcurrentHashMap中取值,要是需要被代理,用AOP生成代理对象,最终生成的Bean存到单例池中; -
销毁Bean:在容器关闭之后销毁
Bean加上@PreDestroy。
SpringMVC的执行流程?
MVC是Model — View — Controler的简称,它是一种架构模式,它分离了表现与交互。它被分为三个核心部件:模型、视图、控制器。
具体流程如下所示:
-
用户发送出请求到【前端控制器
DispatcherServlet】; -
【前端控制器
DispatcherServlet】收到请求调用【处理器映射器HandlerMapping】; -
【处理器映射器
HandlerMapping】找到具体的处理器(可查找xml配置或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给【前端控制器DispatcherServlet】; -
【前端控制器
DispatcherServlet】调用【处理器适配器HandlerAdapter】; -
【处理器适配器
HandlerAdapter】经过适配调用具体的处理器(Handler/Controller); -
Controller执行完成返回ModelAndView对象; -
【处理器适配器
HandlerAdapter】将Controller执行结果ModelAndView返回给【前端控制器DispatcherServlet】; -
【前端控制器
DispatcherServlet】将ModelAndView传给【视图解析器ViewReslover】; -
视图解析器
ViewReslover解析后返回具体View(视图); -
【前端控制器
DispatcherServlet】根据View渲染视图(即将模型数据填充至视图中); -
【前端控制器
DispatcherServlet】响应用户。
SpringMVC的常用注解有哪些?
-
声明Bean到Springmvc容器:
@RestController=@Controller+@ResponseBody,将返回的集合或对象转换为JSON -
设置请求路径:通用的
@RequestMapping、@GetMapping、@PostMapping、@PutMapping、@DeleteMapping; -
接收请求参数:
@RequestBody: 接收请求体中的json数据;@PathVariable:接收请求路径中的参数;@RequestHeader:接收请求头中的参数;@RequestParam:一般用于给参数设置默认值或者完成请求参数和controller方法参数的映射。(指的是接受如http://127.0.0.1/query?name=111&age=12这样的请求中的name、age这样的参数
@Autowired与@Resource区别?
- 来源不同:
@Autowired是spring提供的注解,@Resource是JDK提供的注解; - 默认注入方式不同:
@Autowired默认的注入方式是ByType(根据类型进行匹配),@Resource默认的注入方式是ByName(根据名称进行匹配); - 按名称查找bean的方式不同:
@Autowired可以通过@Qualifier来显示指定的名称,@Resource可以通过name来显示指定名称。
Spring框架如何对bean在实例化之后做特殊处理?
实现BeanPostProcessor接口来对bean进行特殊处理。BeanPostProcessor接口提供了两个方法:postProcessBeforeInitialization和postProcessAfterInitialization。这两个方法会在bean的初始化方法(如果有的话,比如@PostConstruct注解标注的方法)执行前后被调用。
Spring中,loC容器配置方式有哪几种?
XML配置- 注解配置
Java代码配置
Spring事务隔离级别包括?
Spring事务隔离级别比数据库事务隔离级别多一个default,这里的default指的是使用底层数据库默认的隔离级别,如MySQL默认是可重复读,PostgreSQL默认是读已提交。
此外,在进行配置的时候,如果数据库和spring代码中的隔离级别不同,那么以spring的配置为主。