1. 什么是Spring 框架
轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性。
我们⼀般说 Spring 框架指的都是 Spring Framework,他是很多模块的集合,使用这些模块可以很方面的协助我们开发。这些模块是:核心容器,数据访问/集成,Web 、AOP (面向切面编程)、工具,消息和测试模块。 比如: Core Container 中的Core 组件是Spring 所有组件的核心,Beans 组件和Context 组件是实现IOC 和依赖注入的基础, AOP 组件用来实现面向切面编程。
Spring 官网列出的的Spring 的6个特征:
- 核心技术: 依赖注入(DI),AOP, 事件(events), 资源, i18n, 验证,数据绑定,类型转换, SpEL。
- 测试: 模拟对象,TestContext 框架, Spring MVC 测试, WebTestClient。
- 数据访问: 事务,Dao支持,JDBC,ORM, 编组XML。
- Web支持: Spring MVC 和 Spring WebFlux Web 框架。
- 集成: 远程处理,JMS, JCA, JMX, 电子邮件,任务, 调度,缓存。
- 语言: Kotlin,Groovy,动态语⾔。
2. 列举一些重要的Spring 模块
- Spring Core: 基础,Spring 其他所有功能都需要依赖于该类库。主要提供IOC 依赖注入功能。
- Spring Aspects: 该模块为与AspectJ的集成提供⽀持。
- Spring AOP: 提供了面向切面的编程实现。
- Spring JDBC: Java数据库连接。
- Spring JMS: Java消息服务。
- Spring ORM: 用于支持Hibernate等ORM 工具。
- Spring Web: 为创建Web 应用程序提供支持。
- Spring Test: 提供了对JUnit 和 TestNG 测试的支持。
3. @RestController vs @Controller
@Controller 返回⼀个⻚⾯
单独使用@Controller 不加 @ResponseBody 的话一般使用在要返回一个视图的情况,这种情况属于比较传统的Spring MVC 的应用,对应于前后端不分离的情况。
@RestController 返回Json 或XML 形式数据
但@RestController 只返回对象,对象数据直接以JSON 或 XML 形式写入 HTTP 响应中,这种情况属于RESTful Web 服务。
4. Spring IOC & AOP
- IOC
IoC(Inverse of Control:控制反转)是⼀种设计思想,就是 将原本在程序中⼿动创建对象的控制
权,交由Spring框架来管理。 IoC 在其他语⾔中也有应⽤,并⾮ Spring 特有。 IoC 容器是
Spring ⽤来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各
种对象。
将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注⼊。这样可以很⼤
程度上简化应⽤的开发,把应⽤从复杂的依赖关系中解放出来。 IoC 容器就像是⼀个⼯⼚⼀
样,当我们需要创建⼀个对象的时候,只需要配置好配置⽂件/注解即可,完全不⽤考虑对象是如
何被创建出来的。 在实际项⽬中⼀个 Service 类可能有⼏百甚⾄上千个类作为它的底层,假如我
们需要实例化这个 Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可
能会把⼈逼疯。如果利⽤ IoC 的话,你只需要配置好,然后在需要的地⽅引⽤就⾏了,这⼤⼤增
加了项⽬的可维护性且降低了开发难度。
Spring 时代我们⼀般通过 XML ⽂件来配置 Bean,后来开发⼈员觉得 XML ⽂件来配置不太好,
于是 SpringBoot 注解配置就慢慢开始流⾏起来 - AOP
AOP(Aspect-Oriented Programming:⾯向切⾯编程)能够将那些与业务⽆关,却为业务模块所共
同调⽤的逻辑或责任(例如事务处理、⽇志管理、权限控制等)封装起来,便于减少系统的重复
代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
Spring AOP就是基于动态代理的,如果要代理的对象,实现了某个接⼝,那么Spring AOP会使
⽤JDK Proxy,去创建代理对象,⽽对于没有实现接⼝的对象,就⽆法使⽤ JDK Proxy 去进⾏代
理了,这时候Spring AOP会使⽤Cglib ,这时候Spring AOP会使⽤ Cglib ⽣成⼀个被代理对象的
⼦类来作为代理。
当然你也可以使⽤ AspectJ ,Spring AOP 已经集成了AspectJ ,AspectJ 应该算的上是 Java ⽣
态系统中最完整的 AOP 框架了。
使⽤ AOP 之后我们可以把⼀些通⽤功能抽象出来,在需要⽤到的地⽅直接使⽤即可,这样⼤⼤
简化了代码量。我们需要增加新功能时也⽅便,这样也提⾼了系统扩展性。⽇志功能、事务管理
等等场景都⽤到了 AOP - Spring AOP 和 AspectJ AOP 有什么区别?
Spring AOP 属于运⾏时增强,⽽ AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying), ⽽ AspectJ 基于字节码操作(Bytecode Manipulation)。
Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java ⽣态系统中最完整的 AOP 框
架了。AspectJ 相⽐于 Spring AOP 功能更加强⼤,但是 Spring AOP 相对来说更简单,
如果我们的切⾯⽐少,那么两者性能差异不⼤。但是,当切⾯太多的话,最好选择 AspectJ ,
它⽐Spring AOP 快很多。
5. Spring bean
-
Spring 中的bean 的作用域有哪些?
singleton: 唯一的bean 实例,Spring 中的bean 默认都是单例的。
prototype: 每次请求都会创建一个新的bean 实例。
request: 每一次http请求都会产生一个新的bean, 该bean 仅在当前HTTP request 内有效。
session: 每一次http 请求都会产生一个新的bean, 该bean 仅在当前Http session 内有效。 -
Spring 中的单例bean 的线程安全问题了解吗?
单例bean 存在线程问题,主要是因为当多线程操作同一个对象时,对这个对象的非静态成员变量的写操作会存在线程安全问题。
常见的解决方法有两种:
a. 在Bean 对象中尽量避免定义可变的成员变量(不太现实)
b. 在类中定义一个ThreadLocal 成员变量,将需要的可变成员变量保存在ThreadLocal 中( 推荐的方式) -
@Component 和 @Bean 的区别是什么?
- 作用对象不同,@Component 作用于类,@Bean 作用于方法。
- @Component 通常是通过类路径扫描来自动侦测以及自动装配到Spring 容器中(我们可以通过@ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到Spring 的 bean 容器中)。@Bean 注解是我们在标有该注解的方法中定义产生这个bean, @Bean 告诉了Spring 这个某个类的实例,当我需要用它的时候还给我。
- @Bean 注解比@Component 注解的自定义性更强,而且很多地方我们只能通过 @Bean 注解注册bean。 比如我们引用第三方类库中的类需要装配到Spring 容器时,只能通过@Bean 来实现。
-
将一个类声明为Spring 的bean 的注解有哪些?
我们一般使用**@Autowired** 注解自动装配bean,要想把类标识成可用于 @Autowired 注解自动装配的bean 的类,采用一下注解可以实现:
@Component: 通用的注解,可标注任意类为 Spring 组件,如果一个bean 不知道属于哪个层,可以使用@Component 注解标注。
**@Repository:**对应持久层即DAO 层,主要用于数据库相关操作。
@Service: 对应服务层,主要涉及一些逻辑,需要DAO 层。
@Controller: 对应Spring MVC 控制层,接收用户请求,并调用Service 层返回数据给前端页面。 -
Spring 中的bean 声明周期?
- Bean 容器找到配置文件中 Spring Bean 的定义。
- Bean 容器利用Java Reflection API 创建一个Bean 的实例。
- 如果涉及到一些属性值,利用set() 方法设置一些属性值。
- 如果Bean 实现了BeanNameAware 接口,调用setBeanName() 方法,传入bean 的名字。
- 如果Bean 实现了BeanClassLoaderAware 接口,调用 setBeanClassLoader() 方法,传入ClassLoader 对象的实例。
- 于上面类似,如果实现了其他 *.Aware 接口,就调用相应的方法。
- 如果有和加载这个Bean 的Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法。
- 如果Bean 实现了 InitializingBean 接口,执行 afterPropertiesSet() 方法。
- 如果Bean在配置文件中的定义包含 init-method 属性,执行指定方法。
- 如果有和加载这个 Bean的 Spring 容器相关 BeanPostProcessor 对象,执⾏ postProcessAfterInitialization() ⽅法
- 当要销毁Bean 的时候,如果Bean 实现了DisableBean 接口,执行 destory() 方法。
- 当要销毁 Bean 的时候,如果 Bean 在配置⽂件中的定义包含 destroy-method 属性,执⾏指定的⽅法。
6. Spring MVC
- 说说自己对于Spring MVC 了解
MVC 是⼀种设计模式,Spring MVC 是⼀款很优秀的 MVC 框架。Spring MVC 可以帮助我们进⾏更简洁的Web层的开发,并且它天⽣与 Spring 框架集成。Spring MVC 下我们⼀般把后端项⽬分为 Service层(处理业务)、Dao层(数据库操作)、Entity层(实体类)、Controller层(控制层,返回数据给前台⻚⾯) - Spring MVC 工作原理了解吗?
- 客户端(浏览器)发送请求,直接请求到 DispatcherServlet
- DispatcherServlet 根据请求信息调用HandlerMapping, 解析请求对应的 Handler。
- 解析到对应的Handler (也就是我们平常所说的 Controller 控制器)后, 开始由 HandlerAdapter 适配器处理。
- HandlerAdapter 会根据Handler 来调用真正的处理器开处理请求,并处理相应的业务逻辑。
- 处理器处理完业务后,会返回一个ModelAndView 对象,Model 是返回的数据对象,View 是逻辑上的View。
- ViewResolver 会根据View 查找实际的View。
- DispatcherServlet 把返回的 Model 传给 View (视图渲染)
- 把View 返回给请求者(浏览器)
7. Spring 框架中用到了哪些设计模式?
- 工厂设计模式: Spring 使用工厂模式通过 BeanFactory,ApplicationContext 创建 bean 对象。
- 代理设计模式: Spring AOP 功能的实现。
- 单例设计模式: Spring 中的 Bean 默认都是单例的。
- 包装器设计模式: 我们的项⽬需要连接多个数据库,⽽且不同的客户在每次访问中根据需要
会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。 - 观察者模式: Spring 事件驱动模型就是观察者模式很经典的⼀个应⽤。
- 适配器模式: Spring AOP 的增强或通知(Advice)使⽤到了适配器模式、spring MVC 中也是⽤
到了适配器模式适配 Controller
8. Spring 事务
- Spring 管理事务的方式有几种?
- 编程式事务,在代码中硬编码。(不推荐使⽤)
- 声明式事务,在配置⽂件中配置(推荐使⽤)
声明式事务⼜分为两种: - 基于XML的声明式事务
- 基于注解的声明式事务
- Spring 事务中的隔离级别有哪几种?
- Spring 事务中有哪几种事务传播行为?
- @Transactional(rollbackFor = Exception.class) 注解了解吗?
@Transactional 注解作⽤于类上时,该类的所有 public ⽅法将都具有该类型的事务属性,同
时,我们也可以在⽅法级别使⽤该标注来覆盖类级别的定义。如果类或者⽅法加了这个注解,那
么这个类⾥⾯的⽅法抛出异常,就会回滚,数据库⾥⾯的数据也会回滚。
在 @Transactional 注解中如果不配置 rollbackFor 属性,那么事物只会在遇到 RuntimeException 的
时候才会回滚,加上 rollbackFor=Exception.class ,可以让事物在遇到⾮运⾏时异常时也回滚。