「《面试八股文》之 Spring 18卷」
又新鲜出炉了,这次整理了一下关于 spring 的面试题,网上也翻了翻关于 spring 的面试题,汇总了一下,基本都在这里了,当然可能有些过于基本的概念我是直接整理到某一问当中了,就没有单独再开设一问,祝大家面试顺利~
-
1.spring 中都用到了哪些设计模式?
-
2.spring 中有哪些核心模块?
-
3.说一下你理解的 IOC 是什么?
-
4.spring 中的 IOC 容器有哪些?有什么区别?
-
5.那 BeanFactory 和 FactoryBean 又有什么区别?
-
6.@Repository、@Service、@Compent、@Controller它们有什么区别?
-
7.那么 DI 又是什么?
-
8.说说 AOP 是什么?
-
9.动态代理和静态代理有什么区别?
-
10.JDK 动态代理和 CGLIB 代理有什么区别?
-
11.Spring AOP 和 AspectJ AOP 有什么区别?
-
12.spring 中 Bean 的生命周期是怎样的?
-
13.spring 是怎么解决循环依赖的?
-
14.为什么要使用三级缓存,二级缓存不能解决吗?
-
15.@Autowired 和 @Resource 有什么区别?
-
16.spring 事务隔离级别有哪些?
-
17.spring 事务的传播机制有哪些?
-
18.springBoot 自动装配原理?
1.spring 中都用到了哪些设计模式?
-
「1.工厂设计模式」
: 比如通过 BeanFactory 和 ApplicationContext 来生产 Bean 对象
-
「2.代理设计模式」
: AOP 的实现方式就是通过代理来实现,Spring主要是使用 JDK 动态代理和 CGLIB 代理
-
「3.单例设计模式」
: Spring 中的 Bean 默认都是单例的
-
「4.模板方法模式」
: Spring 中 jdbcTemplate 等以 Template 结尾的对数据库操作的类,都会使用到模板方法设计模式,一些通用的功能
-
「5.包装器设计模式」
: 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源
-
「6.观察者模式」
: Spring 事件驱动模型观察者模式的
-
「7.适配器模式」
:Spring AOP 的增强或通知(Advice)使用到了适配器模式
2.spring 中有哪些核心模块?
-
1.
「Spring Core」
:Spring核心,它是框架最基础的部分,提供IOC和依赖注入DI特性
-
2.
「Spring Context」
:Spring上下文容器,它是 BeanFactory 功能加强的一个子接口
-
3.
「Spring Web」
:它提供Web应用开发的支持
-
4.
「Spring MVC」
:它针对Web应用中MVC思想的实现
-
5.
「Spring DAO」
:提供对JDBC抽象层,简化了JDBC编码,同时,编码更具有健壮性
-
6.
「Spring ORM」
:它支持用于流行的ORM框架的整合,比如:Spring + Hibernate、Spring + iBatis、Spring + JDO的整合等
-
7.
「Spring AOP」
:即面向切面编程,它提供了与AOP联盟兼容的编程实现
3.说一下你理解的 IOC 是什么?
首先 IOC 是一个
「容器」
,是用来装载对象的,它的核心思想就是
「控制反转」
那么究竟
「什么是控制反转」
?
控制反转就是说,
「把对象的控制权交给了 spring,由 spring 容器进行管理」
,我们不进行任何操作
那么为
「什么需要控制反转」
?
我们想象一下,没有控制反转的时候,我们需要
「自己去创建对象,配置对象」
,还要
「人工去处理对象与对象之间的各种复杂的依赖关系」
,当一个工程的量起来之后,这种关系的维护是非常令人头痛的,所以就有了控制反转这个概念,将对象的创建、配置等一系列操作交给 spring 去管理,我们在使用的时候只要去取就好了
4.spring 中的 IOC 容器有哪些?有什么区别?
spring 主要提供了
「两种 IOC 容器」
,一种是
「BeanFactory」
,还有一种是
「ApplicationContext」
它们的区别就在于,BeanFactory
「只提供了最基本的实例化对象和拿对象的功能」
,而 ApplicationContext 是继承了 BeanFactory 所派生出来的产物,是其子类,它的作用更加的强大,比如支持注解注入、国际化等功能
5.那 BeanFactory 和 FactoryBean 又有什么区别?
这两个是
「不同的产物」
「BeanFactory 是 IOC 容器」
,是用来承载对象的
「FactoryBean 是一个接口」
,为 Bean 提供了更加灵活的方式,通过代理一个Bean对象,对方法前后做一些操作。
6.@Repository、@Service、@Compent、@Controller它们有什么区别?
这四个注解的
「本质都是一样的,都是将被该注解标识的对象放入 spring 容器当中,只是为了在使用上区分不同的应用分层」
-
-
-
-
@Compent:其他不属于以上三层的统一使用该注解
7.那么 DI 又是什么?
DI 就是依赖注入,其实和 IOC 大致相同,只不过是
「同一个概念使用了不同的角度去阐述」
DI 所描述的
「重点是在于依赖」
,我们说了
「IOC 的核心功能就是在于在程序运行时动态的向某个对象提供其他的依赖对象」
,而这个功能就是依靠 DI 去完成的,比如我们需要注入一个对象 A,而这个对象 A 依赖一个对象 B,那么我们就需要把这个对象 B 注入到对象 A 中,这就是依赖注入
spring 中有三种注入方式
8.说说 AOP 是什么?
AOP 意为:
「面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术」
。
AOP 是
「OOP(面向对象编程) 的延续」
,是 Spring 框架中的一个重要内容,是函数式编程的一种衍生范型。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
「AOP 实现主要分为两类:」
-
「静态 AOP 实现」
, AOP 框架
「在编译阶段」
对程序源代码进行修改,生成了静态的 AOP 代理类(生成的 *.class 文件已经被改掉了,需要使用特定的编译器),比如 AspectJ
-
「动态 AOP 实现」
, AOP 框架
「在运行阶段」
对动态生成代理对象(在内存中以 JDK 动态代理,或 CGlib 动态地生成 AOP 代理类),如 SpringAOP
spring 中 AOP 的实现是
「通过动态代理实现的」
,如果是实现了接口就会使用 JDK 动态代理,否则就使用 CGLIB 代理。
「有 5 种通知类型:」
-
-
「@AfterReturning」
:在目标方法返回或异常后调用
-
「@AfterThrowing」
:在目标方法返回后调用
-
-
「@Around」
:将目标方法封装起来,自己确定调用时机
9.动态代理和静态代理有什么区别?
「静态代理」
-
由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了
-
-
「动态代理」
10.JDK 动态代理和 CGLIB 代理有什么区别?
JDK 动态代理时业务类
「必须要实现某个接口」
,它是
「基于反射的机制实现的」
,生成一个实现同样接口的一个代理类,然后通过重写方法的方式,实现对代码的增强。
CGLIB 动态代理是使用字节码处理框架 ASM,其原理是通过字节码技术为一个类
「创建子类,然后重写父类的方法」
,实现对代码的增强。
11.Spring AOP 和 AspectJ AOP 有什么区别?
Spring AOP 是运行时增强,是通过
「动态代理实现」
的
AspectJ AOP 是编译时增强,需要特殊的编译器才可以完成,是通过
「修改代码来实现」
的,支持
「三种织入方式」
-
「编译时织入」
:就是在编译字节码的时候织入相关代理类
-
「编译后织入」
:编译完初始类后发现需要 AOP 增强,然后织入相关代码
-
主要区别
|
Spring AOP
|
AspecjtJ AOP
|
增强方式
|
运行时增强
|
编译时增强
|
实现方式
|
动态代理
|
修改代码
|
编译器
|
javac
|
特殊的编译器 ajc
|
效率
|
较低(运行时反射损耗性能)
|
较高
|
织入方式
|
运行时
|
编译时、编译后、类加载时
|
12.spring 中 Bean 的生命周期是怎样的?
SpringBean 生命周期大致分为4个阶段:
-
-
-
-
如果实现了 Aware 接口,会通过其接口获取容器资源
-
如果实现了 BeanPostProcessor 接口,则会回调该接口的前置和后置处理增强
-
如果配置了 init-method 方法,]会执行该方法
-
-
如果实现了 DisposableBean 接口,则会回调该接口的 destroy 方法
-
如果配置了 destroy-method 方法,则会执行 destroy-method 配置的方法
13.spring 是怎么解决循环依赖的?
循环依赖就是说两个对象相互依赖,形成了一个环形的调用链路
spring 使用三级缓存去解决循环依赖的,其
「核心逻辑就是把实例化和初始化的步骤分开,然后放入缓存中」
,供另一个对象调用
-
「第一级缓存」
:用来保存实例化、初始化都完成的对象
-
「第二级缓存」
:用来保存实例化完成,但是未初始化完成的对象
-
「第三级缓存」
:用来保存一个对象工厂,提供一个匿名内部类,用于创建二级缓存中的对象
当 A、B 两个类发生循环引用时 大致流程
-
1.A 完成实例化后,去
「创建一个对象工厂,并放入三级缓存」
当中
-
如果 A 被 AOP 代理,那么通过这个工厂获取到的就是 A 代理后的对象
-
如果 A 没有被 AOP 代理,那么这个工厂获取到的就是 A 实例化的对象
-
-
3.B 进行属性注入,需要 A ,则
「从三级缓存中去取 A 工厂代理对象」
并注入,然后删除三级缓存中的 A 工厂,将 A 对象放入二级缓存
-
4.B 完成后续属性注入,直到初始化结束,将 B 放入一级缓存
-
5.
「A 从一级缓存中取到 B 并且注入 B」
, 直到完成后续操作,将 A 从二级缓存删除并且放入一级缓存,循环依赖结束
spring 解决循环依赖有两个前提条件:
-
1.
「不全是构造器方式」
的循环依赖(否则无法分离初始化和实例化的操作)
-