-
- 2.1. Spring中的Bean的作用域有哪些?
- 2.2. 什么是IOC和DI,并简要说明DI是如何实现的?
- 2.3. 什么是Spring中的自动装配?自动装配的方式有哪些?
- 2.4. Spring中的BeanFactory和ApplicationContext的区别是什么?
- 2.5. Spring中的BeanFactory和FactoryBean的区别?
- 2.6. @Autowired和@Resource的区别是什么?
- 2.7. Spring中@Component和@Bean的区别?
- 2.8. Spring中如何区分不同的Bean,生产环境中要测试的Bean和开发环境不同怎么办?
- 2.9. Spring Bean的生命周期
- 2.10. Spring IOC容器的启动过程
-
- 3.1. 什么是Spring中的AOP?
- 3.2. AOP的实现原理?
- 3.3. 如何理解AOP中的连接点,切点,增强,引介,织入,切面?
-
- 4.1. @Transactional注解的添加位置?
- 4.2. @Transcational什么时候触发回滚?
- 4.3. Spring的事务传播机制?
- 4.4. Spring的事务隔离级别?
- 4.5. @Transcational注解实现的原理?
- 4.6. Spring支持的事务管理类型有哪些?
-
- 5.1. Spring是如何解决循环依赖的?
- 5.1.1. 哪些循环依赖是可以解决的?哪些是不可以解决的?
- 5.1.2. Spring的三级缓存机制
- 5.1.3. Spring如何解决循环依赖的?
- 5.2. 为什么三级缓存?
- 5.1. Spring是如何解决循环依赖的?
-
- 6.1. 什么是Spring MVC?简单介绍一下你对Spring MVC的理解?
- 6.2. Spring MVC的流程
- 6.3. Spring MVC的主要组件?
- 6.4. Spring MVC是如何进行全局异常处理的?
- 6.4.1. 实现Spring的异常处理接口HandlerExceptionResolver
- 6.4.2. @ExceptionHandler注解
-
- 7.1. SpringBoot自动装配的原理
- 7.2. SpringBootApplication注解
1. Spring是什么?
1.1. 请说一下Spring为企业级开发带来的好处?
- 非侵入式:不强制要求实现Spring框架中的接口或者继承Spring框架中的类
- IOC容器:IOC容器帮助应用程序管理对象以及对象之间的依赖关系
- AOP:将所有横切关注功能封装到切面,通过配置的方式将横切关注的功能动态添加到目标代码,实现了业务逻辑和系统服务之间的分离
- 事务管理:Spring可以集成多种常用的持久层技术,并且提供了声明式事务管理,可以直接使用@Transactional注解完成事务的管理
- MVC:SpringMVC为web表示层提供了更好的解决方案
1.2. @Controller和@RestController的区别?
@RestController相当于@ResponseBody + @Controller
@ResponseBody的作用是将返回值结果序列化为JSON格式作为HTTP的返回值,如果不适用该注解,则Spring会返回一个视图
2. IOC
2.1. Spring中的Bean的作用域有哪些?
共有五种,可以通过@scope注解来设定
-
singleton:<1>Bean以单例存在,IOC容器中只会存在一个共享的Bean实例对象 <2>可以设置lazy-init = true来实现懒加载(默认bean是启动时refresh()初始化的,而lazy-init的bean是context.getBean()初始化的 <3>适用于无状态的bean
-
prototype:<1>prototype是原型类型,其在启动的时候不会实例化,而当我们获取bean的时候才会去创建一个对象,并且每次获取的都不是同一个对象 <2>适用于有状态的bean
还有三种是在MVC的WebApplicationContext中
-
request:每一次HTTP请求会创建了一个bean,该bean仅在当前HTTP request内有效,当请求结束了该对象的生命周期也就结束了
-
session:每个用户共享一个session bean,生命周期同http session,request.getSession()
-
global session:所有用户共享一个global session bean,生命周期同http session,需要线程安全防护。
2.2. 什么是IOC和DI,并简要说明DI是如何实现的?
2.2.1. IOC
IOC是指的控制反转。<1>IOC意味设计好的对象交给IOC容器 <2>IOC容器还可以帮我们查找并且注入依赖,对象由主动变为被动,所以叫做反转 <3>IOC一个重点是系统运行的时候,动态的向某个对象提供它所需要的其他对象,这一点是通过依赖注入实现的。
2.2.2. DI
DI指的是依赖注入,依赖注入有两种方式实现:
- 使用XML手动注入:<1>通过配置property属性实现调用setter方法(底层是反射)来进行注入 <2>通过constructor-arg元素实现带参数构造器的注入
- 使用注解的自动注入(自动装配,见下面)
2.3. 什么是Spring中的自动装配?自动装配的方式有哪些?
Spring的自动装配就是Spring帮助我们在上下文自动查找,并自动给bean装配与其相关的属性
Spring中自动装配的方式有以下几种:
- byType:使用@Autowired先根据bean的type查找,如果有多个再根据bean的name查找
- byName:使用@Resource现根据bean的name查找,如果多个再根据bean的type查找
- 构造器装配:在类构造器上使用@Autowired注解,Spring会自动将构造函数的参数装配进来
- autodect:如果只有一个有参构造器,spring会自动注入,无需实现
2.4. Spring中的BeanFactory和ApplicationContext的区别是什么?
- BeanFactory:Spring中最底层的接口,只提供了最基本的容器的功能比如实例化bean和getBean,ApplicationContext则实现了BeanFactory接口,在beanFactory的基础上提供了很多扩展的功能,比如对bean的生命周期的管理。从refresh()函数就能看出来它有对整个bean生命周期的管理,比如beanPostProcessor以及AOP。
- 两者在装载bean上也有区别,beanFactory在启动的时候不会去实例化bean,只能从容器中getBean的时候才会去实例化。而ApplicationContext启动的时候就会去扫描对应的bean并且去实例化,但是可以为bean配置lazy-init进行延迟初始化。
2.5. Spring中的BeanFactory和FactoryBean的区别?
- beanFactory是接口,提供了IOC最基本的接口如创建bean实例和获取bean
- FactoryBean也是接口,但是是一个bean,通过创建getObject()方法可以灵活的生产和创建新的对象。本质上是给Bean的创建增加了简单的工厂模式和装饰模式。
DEMO:
@Component
public class FirstFactoryBean implements FactoryBean<TargetObject> {
@Override
public TargetObject getObject() throws Exception {
TargetObject targetObject = new TargetObject();
targetObject.setA(3);
return targetObject;
}
}
TargetObject factoryBean = (TargetObject) context.getBean("firstFactoryBean");
System.out.println(factoryBean.getA());
// 3
2.6. @Autowired和@Resource的区别是什么?
- <1> @Autowired注解是默认按照byType依赖对象,如果多个同类型才会去byName。<2>如果想用byName,可以配合@Qualifier来使用
@Autowired()
@Qualifier("demoB")
private DemoB demoB;
- <1>@Resource注解默认按照byName来自动注入,只有当多个name相同的才会使用byType的方式进行注入
2.7. Spring中@Component和@Bean的区别?
- Component注解表明⼀个类将作为组件类,并告诉Spring要为这个类创建Bean
- Bean常用于方法中,并且告诉Spring要为该返回的类创建Bean
2.8. Spring中如何区分不同的Bean,生产环境中要测试的Bean和开发环境不同怎么办?
- @Autowired的时候使用@Qualifier来标注不同的bean
- 使用@Primary配合@Component或者@Bean,优先加载@Primary的Bean(区分开发环境和生产环境)
2.9. Spring Bean的生命周期
- 构造器创建Bean
- 给Bean对象设置相关的属性(set方法)
- 调用bean的后置处理器的before方法
- 调用bean的初始化(init-method/post-construct接口的init())
- 调用bean的后置处理器
- bean对象创建完成
- bean对象的销毁(配置destroy()方法)
2.10. Spring IOC容器的启动过程
- 起点是new ClassPathXmlApplicationContext,传入xml配置文件的地址
- 执行核心方法refresh()
- 创建BeanFactory,创建一个DefaultListableBeanFactory,用于存放后续所有的bean。在这里通过扫描xml获得bean的定义并进行beanDefinition的加载,解析然后放入Map中
- 初始化BeanFactory工厂,添加一些特殊的后置处理器比如ApplicationContextAwareProcessor,为了让bean能够感知ApplicationContext,需要在后置处理器中设置其ApplicationContext。
- 调用BeanFactoryPostProcessors,在实例化bean之前再对beanDefinition做一些自定义修改
- 注册一些后置处理器,以及注册一些监听器等资源
- 实例化所有的非懒加载的单例对象,首先判断有没有设置内置的值处理器,比如处理xml属性中一些特殊${}之类的处理器,没有使用默认的EmbbedResolver。然后把所有的BeanDefinitionNames一个一个遍历,判断是不是单例的,是不是懒加载的,并且还不能是FactoryBean(单独处理),如果都不是则进入getBean()。这里面先检查是否在缓存Map中存在了,三层缓存用来解决循环依赖问题。(对于非单例对象不予解决循环依赖,直接抛出异常)
3. AOP
3.1. 什么是Spring中的AOP?
将那些与业务无关却为业务模块所共用调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度
3.2. AOP的实现原理?
- Spring AOP的实现原理是动态代理,动态代理有两种方式,一种是JDK代理另一种是cglib动态代理
- JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口,如果目标类没有实现接口,那么Spring AOP会选择使用cglib来动态代理。
3.3. 如何理解AOP中的连接点,切点,增强,引介,织入,切面?
a. 从额外逻辑的角度看
1. 横切关注点:分散在各个模块中的共同问题,如日志管理
2. 切面:横切关注点的实现。一般切面由切点和通知,(引介)来实现
1. 切点:指的是在哪个方法增加额外的逻辑。使用@PointCut定义切点,或者使用execution(* com.example.orderservice.*.*(..))表达式来匹配切点。
2. 通知:通知方法指的是在调用目标方法前后执行的额外逻辑
3. 引介:引介可以动态的让某个业务类实现原本没有被实现的接口
b. 从核心逻辑的角度看
- 增强:就是你想要增强的功能,比如 安全,事务,日志等
- 连接点:spring允许你使用通知的地方,例如方法的执行,异常的处理
c. 织入:织入是将增强添加到目标类具体连接点上的过程

4. 事务
4.1. @Transactional注解的添加位置?
- 接口实现类或者接口实现类的方法上,而不是接口中
- 当添加到接口实现类中,表明接口实现类下的所有方法都被@Transactional修饰,当添加到某个方法上时,则只有该方法被修饰
- 需要注意的是,只有访问权限为public的方法才起作用
4.2. @Transcational什么时候触发回滚?
- @Transcational注解只有在抛出运行时异常或者错误的时候才会触发事务的回滚
- 常见的非运行时异常不会触发事务的回滚,但是我们平常做的业务处理的时候,需要捕获异常,所以可以手动抛出异常
4.3. Spring的事务传播机制?
- REQUIRED(默认):如果当前已经开启了事务,则复用当前事务,否则新建事务,适合增删改
- REQUIRED_NEW:不论当前是否开启事务,都新建一个事务,之前的事务会被挂起,适合log
- SUPPORTS:如果当前有事务,复用当前事务,如果当前没有事务,就以非事务方式运行,适合查
- NOT_SUPPORTS:以非事务方式执行,如果当前存在事务,就把当前事务挂起
- MANDATORY:支持当前事务,如果没有事务就抛出异常
- NEVER:非事务方式运行,如果存在事务就抛出异常
- NESTED:如果有活动事务,则运⾏在⼀个嵌套的事务中,如果没有活动事务,则新建一个事务。如果外部事务回滚,则里面的事务也回滚。否则如果只有里面的事务回滚,那么外层的事务不回滚
4.4. Spring的事务隔离级别?
- ioslation_default:默认的事务隔离级别,使用数据库默认的隔离级别
- ioslation_read_uncommited:读未提交
- ioslation_read_commited:读已提交
- ioslation_repeatable_read:可重复读
- ioslation_serializable:可串行化
4.5. @Transcational注解实现的原理?
- 事务开始的时候通过AOP机制,生成一个代理机制
- 声明的@Transcational的目标方法被拦截器拦截之后,会在目标方法开始执行之前创建并加入事务(autocommit = false),并执行目标方法的逻辑,然后根据执行情况是否异常来决定是否需要提交或者回滚
4.6. Spring支持的事务管理类型有哪些?
- Spring支持编程式事务管理和声明式事务管理,使用声明式事务可以解耦合,编程式事务可以更准确的控制事务
- 事务分为全局事务和局部事务,全局事务由应⽤服务器管理,局部事务和底层采⽤的持久化⽅案有关,这些事务的⽗接⼝都是PlatformTransactionManager。
5. 循环依赖/三级缓存
5.1. Spring是如何解决循环依赖的?
5.1.1. 哪些循环依赖是可以解决的?哪些是不可以解决的?
- 基于构造器的单例循环依赖不可以解决,出现循环依赖会抛异常
- 基于设置值setter的单例循环依赖是可以解决的
- 原型对象的循环依赖不可以解决
5.1.2. Spring的三级缓存机制
一级缓存(singletonObjects)
bean实例化完毕,属性注入完毕,初始化完毕后的单例放入一级缓存
二级缓存(earlySingletonObjects)
bean实例化完成,并从三级缓存拿出后创建代理对象放入二级缓存
三级缓存(singletonFactories)
bean实例化完成就放到三级缓存中
5.1.3. Spring如何解决循环依赖的?
使用了三级缓存解决循环依赖,在doGetBean的方法中,依次从第一、第二、第三级缓存中先尝试获取Bean。

A依赖B,B依赖A。创建A,在A实例化后放入三级缓存,然后注入属性,注入的时候发现依赖B,就去创建B,完成B的实例化后放入三级缓存,在进行B的属性注入的时候发现依赖A。在doGetBean(A)的时候发现三级缓存已经存在A的工厂,从中得到A的代理对象放入二级缓存并删除三级缓存。接着继续完成B的初始化,创建完后放入一级缓存。A再完成初始化放入一级缓存。
5.2. 为什么三级缓存?
假如只有二级缓存,由于Spring的历史原因会把属性注入和后置处理器两个过程分开。那么一开始放入二级缓存的是普通bean对象,经过AOP后放入二级缓存的是代理对象,把原来的普通bean对象覆盖。这样假如A同时循环依赖B和C,B和C在属性注入doGetBean(A)的时候可能会分别拿到普通bean和代理bean,造成错误。
其实如果不考虑Spring规范原则原因,规定放入二级缓存的都是代理对象就可以了。
6. Spring MVC
6.1. 什么是Spring MVC?简单介绍一下你对Spring MVC的理解?
SpringMVC是一个基于MVC设计模式实现的请求驱动类型的轻量级web框架,通过Model、View、Controller分离,将Web层进行职责解耦,把复杂的web应用分成清晰的几个部分,简化开发。
6.2. Spring MVC的流程

-
request请求发送到DispatcherServlet,DispatcherServlet去查看RequestMapping得到Handle执行链(一个Handler处理器即controller,多个Handler拦截器)。
-
DispatcherServlet用Handler请求HandlerAdpater去执行特定的Controller方法,得到ModelAndView返回给DispatcherServlet
-
DispatcherServlet请求View Resolver解析ModelAndView并返回View,由DispatcherServlet将数据填充到视图,并放入response中返回给前端
6.3. Spring MVC的主要组件?
-
DispatcherServlet:接收请求,响应结果。相当于转发器,减少了各个组件的偶合
-
RequestMapping:根据请求的URL生成handlerChain
-
HandlerAdapter:根据Handler执行具体的Controller方法
-
View Resolver:解析视图,根据视图逻辑名解析出真正的视图
6.4. Spring MVC是如何进行全局异常处理的?
6.4.1. 实现Spring的异常处理接口HandlerExceptionResolver
实现HandlerExceptionResolver接口,并重写resolveException方法
6.4.2. @ExceptionHandler注解
@ControllerAdvice增强Handler,@ExceptionHandler注解声明异常处理具体类型
7. SpringBoot
7.1. SpringBoot自动装配的原理
- 通过@EnableAutoConfiguration注解,SpringBoot 在启动时会去依赖的starter包中寻找 resources/META-INF/spring.factories 文件,然后根据文件中配置的Jar包去扫描项目所依赖的Jar包,这类似于 Java 的 SPI 机制。
- 根据 spring.factories配置加载AutoConfigure类。
- 根据 @Conditional注解的条件,进行自动配置并将Bean注入Spring Context 上下文当中。也可以使用@ImportAutoConfiguration({MyServiceAutoConfiguration.class}) 指定自动配置哪些类。
7.2. SpringBootApplication注解
- @SpringBootConfiguration注解:继承了@Configuration,表明当前是java config类,会被自动加载到IOC容器中
- @EnableAutoConfiguration注解:自动装配
- @ComponentScan注解:扫描路径设置,扫描默认包或指定包下⾯的符合条件的组件并且加载,⽐如被 标注了Component注解的或者被标注了Controller注解的