Spring常见面试题笔记

1.Bean的作用范围

1.prototype:为每一个bean请求单独创建一个
2.singleton:单例,默认实现,由BeanFactory管理
3.request:为每一个网络请求单独创建一个实例
4.session:为每一个会话创建一个实例,和request差不多
5.application:为每一个web应用创建一个实例
6.websocket:为每一个websocket应用创建一个实例

2.Bean的生命周期

1.实例化
2.属性赋值(依赖注入)
3.初始化
(1)Aware:实现了Aware接口的方法会被Spring调用,主要用来获取Spring容器的上下文信息
(2)BeanPostProcessor的before方法:常用于AOP
(3)InitialBean的afterSetProperties
(4)xml配置的init-method 等同于@PostConstruct标注的方法
(5)BeanPostProcessor的after方法
4.销毁

2.事务的传播行为

@Transactional(rollbackfor = Expection.class,propagetion = Propagation.REQUIRED)
rollbackfor可以指定事务回滚的条件,默认是RuntimeExpection才会回滚,碰到编译异常就不会。
propagation是事务的传播行为,指一个事务方法被另一个事务方法调用时应该如何控制事务。
1.REQUIRED,Spring事务默认属性,会检查调用者是否开启事务,有则加入,没有则新建一个事务
2.REQUIRED_NEW,不管啊有没有别的事务,总会开启一个新的事物
3.SUPPORTS,如果调用者开启事务,则加入该事务,没有则不开启事务
4.NOT_SUPPORTED,不支持事务,在无事务状态下运行,如果调用者有事务,则将该事物挂起,执行完自己的代码后再恢复
5.NEVER,必须没有事务,否则抛异常
6.MANDATORY,必须有事务,否则抛异常

3.事务的隔离级别

在数据库执行并发事务时会出现三个问题,严重性依次增加。
1.脏读
一个事务读取到另一个事物还没提交的数据,叫做脏读。(当时学到这里会很疑惑,为什么明明没有提交,却能被读取到数据,难道在事务操作时写入了磁盘吗)

2.不可重复读
一个事物先后读取同一条记录,两次结果不一样,叫做不可重复读。不可重复读一般是由针对某条记录的更新操作造成的。

3.幻读
一个事务在查询时没有记录,但是插入时又发现了一条记录,前后查询结构不一致,叫做幻读。幻读一般在查询时有其他线程增删造成。

不可重复读和幻读可以区别记忆。

4.隔离级别:

数据库采用了不同的策略应对并发问题,这种策略叫隔离级别
1.READ UNCOMMITTED:中文意思可以读未提交的,这就解开了我之前的疑问,事务提交前的改动能不能被读取到看的是配置功能。
这个是数据库最低的隔离级别,允许脏读、不可重复读、幻读
2.READ COMMITTED:可以读提交的数据。
该级别禁止了脏读,但是允许不可重复读、幻读
3.REPEATABLE READ:MySQL默认隔离级别
该级别禁止了脏读和不可重复读,但是允许幻读
4.SERIALIZABLE:串行化,性能较低
该级别禁止了脏读、不可重复读、幻读
5.DEFAULT:Spring提供了一个额外选项,它使用数据库默认的隔离级别

5.事务失效

要想理解事务的失效原因,必须知道事务的实现是AOP,而AOP的实现是CGlib,CGlib特有的继承式代理造成一系列原因。

  1. 方法的自调用:这算是个比较正式的考点,在开启了事务的方法中调用本类下的其他方法(即使这个方法也开启了事务)就会导致失效。因为开了事务的方法是AOP生成的代理类调用的,当他调用被代理类其他方法时,调用的是未被事务增强过的方法(方法本身)这个问题即使控制传播行为也无法解决
    解决方法
    (1)自己注入自己
    (2)方法拆分到新的类中
    (3)@EnableAspectJAutoProxy(exposeProxy = true) + AopContext.currentProxy()
  2. 方法是private:由于CGlib创建的代理类是继承自目标类,目标类中的private方法子类访问不到
  3. 方法是final:和private同理,CGlib的继承结构决定了这些关键字的限制

以上三个方法都是由于AOP机制引起的

  1. 单独的线程调用方法(异步调用):异步调用开启了新线程,而新线程中没有之前的数据库连接信息
  2. 抛出了特定异常:默认回滚的异常为RuntimeExpection和Error,如果需要自定义可以在@Transactional中指定rollbackfor
  3. 方法中捕获了异常:如果你在方法中主动捕获异常而没有抛出,事务管理器无法回滚
  4. 错误的传播行为:如果你指定了NOT_SUPPORTED或NEVER这种不支持事务的传播行为,就会失效
  5. 类没有被Spring管理或数据源和连接池没有被Spring管理

6.依赖注入的方式

  1. 构造器注入:注入的Bean不可变。当出现多个重载的构造函数,可以用@Autowire指定要注入的函数。会出现循环依赖。
  2. setter注入
  3. 属性注入

Spring推荐使用构造器注入而不是属性注入,因为构造器注入可以保证属性不为null值,同时属性不可变(相当于用了final修饰)

7.AOP的通知类型

  1. Before:前置通知,在方法执行前被调用
  2. After-Returning:后置通知,在方法完成时被调用
  3. After-Throwing:异常通知,在方法抛出异常时被调用
  4. After:最终通知,在方法执行完成后被调用,无论方法是否成功
  5. Round:环绕通知,在方法执行前后调用

8.循环依赖和三级缓存

想要读懂循环依赖需要先理清Bean的生命周期

循环依赖:Spring中两个Bean相互依赖,比如A中需要注入B,B中要注入A
解决方法:三级缓存
三级缓存:
一级缓存里存放了完整的Bean,也叫单例池
二级缓存里存放了刚完成实例化的Bean。从Bean的生命周期我们可以知道,此时的Bean还没有到属性赋值(依赖注入)这一环,所以不会有循环依赖
三级缓存里存放了Bean对应的工厂类,用来专门处理代理对象的循环依赖问题

回到我们举得ABA循环依赖的例子,
1.当你创建A时,先在实例化之后将这个不完整的A放到二级缓存,下一步要注入B时,会去一级缓存里找,没有再去二级缓存里找,都没有就创建B。
2.同样的,B在实例化完成之后要注入A,在二级缓存里找到了这个不完整的A,将他注入,完成后续的生命周期直到完成创建,此时会将B放入一级缓存。
3.这时我们回到还没完成的第1条,A找到了在一级缓存的B,可以顺利执行注入,完成相关生命周期。

其实只需要二级缓存就能解决循环依赖问题,但因为代理类的存在,需要额外设置三级缓存。
如果不设置三级缓存,那二级缓存里存放的都是原始的Bean,AOP的功能就用不了
如果把代理类提前创建放到二级缓存里,那就违反了Bean的生命周期,因为代理类的创建是在Bean的初始化的BeanPostProcessor执行的,而二级缓存是在实例化之后就开始了。

9.Spring的模块

  1. Spring Core:Spring的核心模块,实现了IOC和DI的功能
  2. Spring AOP:提供了面向切面编程的能力,Spring集成了AspectJ的部分功能来帮助开发者实现非侵入式的代码增强
  3. Spring Beans:创建和管理了Bean的生命周期
  4. Spring Context:上下文功能,提供国际化、时间监听、资源访问、环境信息获取等功能
  5. Spring MVC:提供了Web开发的MVC三层架构
  6. Spring Data:提供了一整套完整的持久化解决方案

10.SpringAOP和AspectJ的区别

SpringAOP:运行时的代理机制(动态代理);基于Spring框架,适用于Spring容器管理的Bean轻量级,使用方便
AspectJ:支持编译时类加载时运行时AOP;更加灵活的切入和增强;编译器和加载期的织入方式,性能较高

11.Spring MVC的理解

MVC是一种编程思想,规定了Web开发中的Model、View、Controller三层。
SpringMVC是对传统MVC的一种拓展,将Model拆分成了业务模型(Service)和数据模型(Repository),将Controller拆分成了DispatchServlet和Controller。简单来说,SpringMVC就是Spring结合Servlet实现的MVC架构
DispatchServlet接收请求,并交给HandlerMapping,根据请求路径匹配合适的后端控制器Controller,这中间会经过HanderAdapter将数据绑定到对象并交给Controller。控制器返回ModelAndView对象会交给ViewResolver解析出前端页面返回
拦截器会在HanderAdapter调用preHandler,在控制器返回时调用postHandler

12.Spring的优点

  1. IOC,控制反转和依赖注入简化了开发过程,降低了耦合度
  2. AOP,非侵入式地增强了代码
  3. 生态丰富,Spring集成了所有主流的java开发技术栈
  4. 社区活跃,文档丰富,解决方案多

13.Spring的设计模式

  1. 单例模式:毫无疑问,Spring最核心的功能就是实现了单例Bean
  2. 工厂模式:同上,整个Spring容器就是一个大型的Bean工厂
  3. 观察者模式:Spring设有监听器来监听各个事件的发布
  4. 适配器模式:SpringMVC中有一个HandlerAdapter专门处理相关适配
  5. 代理模式:AOP就是通过代理对象完成的方法增强
  6. 模板方法模式:Spring提供了很多的Template给开发者调用

14.Spring的父子容器

指的是在Spring整合SpringMVC时通常会出现2个容器,他们之间呈现父子关系
父容器通常是Spring的Bean容器,子容器通常是一个Web容器如Servlet容器
子容器可以访问父容器中的Bean,可以方便访问Service和Dao
父容器无法访问子容器的Bean,避免了不必要的耦合
避免了重复Bean的冲突

15.Spring的启动流程

  1. 读取配置
  2. 实例化容器
  3. 解析BeanDefinitions
  4. 执行Bean生命周期
  5. 发布事件
  6. 完成启动
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值