1. 什么是Spring框架?
Spring是一个轻量型的开发框架,旨在提高开发人员的开发效率和系统的可维护性
Spring的6个特征:
- 核心技术
- 测试
- Web支持
- 集成
- 语言
1.1 列举一些重要的Spring模块
- Spring Core:基础,Spring其他所有的功能都需要依赖该类库,主要提供IOC依赖注入功能
- Spring Aspects:该模块为与AspectJ的集成提供支持
- Spring Aop:提供了面向切面的编程实现
- Spring JMS:Java消息服务
- Spring ORM: 用于支持Hibernate等ORM工具
- Spring Web:为创建Web应用程序提供支持
- Spring Test:提供了对JUnit和TestNg测试的支持
1.3 @RestController 和@Controller
@Controller 返回的是一个视图
@RestController = @ResponseBody + @Controller 返回JSON或者XML形式数据
(返回对象,对象数据以xml或者JSON的格式写入到HTTP响应(Response)中)
@ResponseBody注解的作用是将@Controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到HTTP 响应(Response)对象的 body 中,通常用来返回 JSON 或者 XML 数据,返回 JSON 数据的情况比较多。
1.4 Spring IOC&AOP
IOC:它是一种设计思想,将程序中手动创建对象的控制权移交给Spring框架来管理。IOC容器是Spring用来实现IOC的载体,IOC容器实际上就是个Map(Key,value),Map中存放的是各种对象。
将对象之间的相互依赖关系交给IOC容器来管理,由IOC容器来完成对象的注入。IOC容器就像一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的
Spring IOC的初始化过程:

IOC的依赖倒置:

转变——–>

1.5 SpringAOP和AspectJAOP区别?
SpringAOP是运行时增强,AspectJAOP是编译时增强,前者基于代理,后者基于字节码操作;
1.6 Spring中的Bean的作用域有哪些?
- Singleton:唯一的Bean实例,Spring默认bean都是单例的
- prototype:每次请求都会创建一个新的实例
- request:每一次HTTP请求都会产生一个新的Bean,该Bean仅在当前HTTP request内有效
- session:每一次HTTP请求都会产生一个新的Bean,该Bean仅在当前HTTP session内有效
- global-session:与session不同的是,所有的session共享一个session Bean,Spring5已经移除
Spring创建Bean的时候如果没有配置作用域,默认是Singleton作用域

1.7 Spring中的单例Bean的线程安全问题了解吗?
当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题
解决方式:
- 在Bean对象中避免定义可变的成员变量(不现实)
- 在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal中
注:ThreadLocal 中文较为准确的叫法为 线程局部变量
1.8 @Component 和 @Bean 区别?
- 作用对象不同
@Component注解用于类,@Bean注解用于方法 @Component通常是通过类路径扫描自动侦测装配到Spring容器当中(@ComponentScan注解定义要扫描的路径)。@Bean注解通常是我们在标有该注解的方法中定义产生这个bean,@Bean会告诉Spring这是某个类的示例,当我需要的时候还给我;@Bean注解比@Component注解的自定义性更强,更灵活,很多地方我们只能通过@Bean来注册Bean。例如我们引用第三方库中的类需要装配到Spring容器的时候,这时候只能通过@Bena来完成
1.9 将一个类声明为Spring的Bean的注解有哪几个?
我们一般使用 @Autowired 注解自动装配 bean,要想把类标识成可用于 @Autowired 注解自动装配的 bean 的类,采用以下注解可实现:
- @Component
- @Service
- @Controller
- @Repository
2.0 Spring中的Bean的生命周期?
- Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化
- Bean实例化后对将Bean的引入和值注入到Bean的属性中
- 如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法
- 如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
- 如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。
- 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。
- 如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用
- 如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。
- 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
- 如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。
2.1 谈谈对Spring MVC的了解?
简单原理图:
用户发起请求,前端控制器接收数据并拦截请求,调用service层,service调用dao层返回处理结果,控制器接收结果返回,通过视图渲染返回视图
2.2 Spring MVC工作原理?

- 客户端(浏览器)发送请求,直接请求到 DispatcherServlet。
- DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。
- 解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由 HandlerAdapter 适配器处理。
- HandlerAdapter 会根据 Handler 来调用真正的处理器开处理请求,并处理相应的业务逻辑。
- 处理器处理完业务后,会返回一个 ModelAndView 对象,Model 是返回的数据对象,View 是个逻辑上的 View。
- ViewResolver 会根据逻辑 View 查找实际的 View。
- DispaterServlet 把返回的 Model 传给 View(视图渲染)。
- 把 View 返回给请求者(浏览器)
2.2 Spring框架中用到了哪几个设计模式?
- 工厂设计模式:Spring工厂模式 通过
BeanFactory和ApplicationContext创建Bean对象 - 单例设计模式:Spring中 Bean默认都是单例
- 代理设计模式:Spring中AOP功能的实现
- 包装器设计模式:项目需要连接多个数据库,可以根据用户需求动态切换不同的数据源
- 适配器模式:Spring AOP的增强或者通知使用到了适配器模式,SpringMVC也使用到了,适配Controller;
- 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用
2.3 Spring管理事务的方式有几种?
- 编程式事务:在代码中硬编码
- 声明式事务:在配置文件中配置
声明式事务分为两种:
- 基于XML的声明式事务
- 基于注解的声明式事务
2.4 Spring 事务中的隔离级别有哪几种?
和MySQL事务隔离级别类似,但多了一个默认的隔离级别
- TransactionDefinition.ISOLATION_DEFAULT: 使用后端数据库默认的隔离级别,Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别.
- TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
- TransactionDefinition.ISOLATION_READ_COMMITTED: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
- TransactionDefinition.ISOLATION_REPEATABLE_READ: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
- TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别
2.5@Transactional(rollbackFor = Exception.class)注解了解吗?
我们知道:Exception分为运行时异常RuntimeException和非运行时异常。事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性。
当@Transactional注解作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。如果类或者方法加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。
在@Transactional注解中如果不配置rollbackFor属性,那么事物只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事物在遇到非运行时异常时也回滚。
2.6 Spring事务中哪几种事务传播行为?
- 支持当前事务:
- TransactionDefinition.PROPAGATION_REQUIRED: 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
- TransactionDefinition.PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
- TransactionDefinition.PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)
- 不支持当前事务
- TransactionDefinition.PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
- TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
- TransactionDefinition.PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。
- 其他情况
- TransactionDefinition.PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。