mirror of
https://github.com/Snailclimb/JavaGuide
synced 2025-08-14 05:21:42 +08:00
[docs update]Spring常见面试题总结完善
This commit is contained in:
parent
98ec9ae28a
commit
16b86763b6
@ -9,71 +9,84 @@ tag:
|
|||||||
|
|
||||||
下面的很多问题我自己在使用 Spring 的过程中也并没有注意,自己也是临时查阅了很多资料和书籍补上的。网上也有一些很多关于 Spring 常见问题/面试题整理的文章,我感觉大部分都是互相 copy,而且很多问题也不是很好,有些回答也存在问题。所以,自己花了一周的业余时间整理了一下,希望对大家有帮助。
|
下面的很多问题我自己在使用 Spring 的过程中也并没有注意,自己也是临时查阅了很多资料和书籍补上的。网上也有一些很多关于 Spring 常见问题/面试题整理的文章,我感觉大部分都是互相 copy,而且很多问题也不是很好,有些回答也存在问题。所以,自己花了一周的业余时间整理了一下,希望对大家有帮助。
|
||||||
|
|
||||||
## 什么是 Spring 框架?
|
## Spring 基础
|
||||||
|
|
||||||
|
### 什么是 Spring 框架?
|
||||||
|
|
||||||
Spring 是一款开源的轻量级 Java 开发框架,旨在提高开发人员的开发效率以及系统的可维护性。
|
Spring 是一款开源的轻量级 Java 开发框架,旨在提高开发人员的开发效率以及系统的可维护性。
|
||||||
|
|
||||||
Spring 翻译过来就是春天的意思,可见其目标和使命就是为 Java 程序员带来春天啊!感动!
|
我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发,比如说 Spring 支持 IoC(Inverse of Control:控制反转) 和 AOP(Aspect-Oriented Programming:面向切面编程)、可以很方便地对数据库进行访问、可以很方便地集成第三方组件(电子邮件,任务,调度,缓存等等)、对单元测试支持比较好、支持 RESTful Java 应用程序的开发。
|
||||||
|
|
||||||
> 题外话 : 语言的流行通常需要一个杀手级的应用,Spring 就是 Java 生态的一个杀手级的应用框架。
|
|
||||||
|
|
||||||
我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。
|
|
||||||
|
|
||||||
比如说 Spring 自带 IoC(Inverse of Control:控制反转) 和 AOP(Aspect-Oriented Programming:面向切面编程)、可以很方便地对数据库进行访问、可以很方便地集成第三方组件(电子邮件,任务,调度,缓存等等)、对单元测试支持比较好、支持 RESTful Java 应用程序的开发。
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Spring 最核心的思想就是不重新造轮子,开箱即用!
|
Spring 最核心的思想就是不重新造轮子,开箱即用,提高开发效率。
|
||||||
|
|
||||||
|
Spring 翻译过来就是春天的意思,可见其目标和使命就是为 Java 程序员带来春天啊!感动!
|
||||||
|
|
||||||
|
🤐 多提一嘴 : **语言的流行通常需要一个杀手级的应用,Spring 就是 Java 生态的一个杀手级的应用框架。**
|
||||||
|
|
||||||
Spring 提供的核心功能主要是 IoC 和 AOP。学习 Spring ,一定要把 IoC 和 AOP 的核心思想搞懂!
|
Spring 提供的核心功能主要是 IoC 和 AOP。学习 Spring ,一定要把 IoC 和 AOP 的核心思想搞懂!
|
||||||
|
|
||||||
- Spring 官网:<https://spring.io/>
|
- Spring 官网:<https://spring.io/>
|
||||||
- Github 地址: https://github.com/spring-projects/spring-framework
|
- Github 地址: https://github.com/spring-projects/spring-framework
|
||||||
|
|
||||||
## 列举一些重要的 Spring 模块?
|
### Spring 包含的模块有哪些?
|
||||||
|
|
||||||
下图对应的是 Spring4.x 版本。目前最新的 5.x 版本中 Web 模块的 Portlet 组件已经被废弃掉,同时增加了用于异步响应式处理的 WebFlux 组件。
|
**Spring4.x 版本** :
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**Spring Core**
|
**Spring5.x 版本** :
|
||||||
|
|
||||||
核心模块, Spring 其他所有的功能基本都需要依赖于该模块,主要提供 IoC 依赖注入功能的支持。
|

|
||||||
|
|
||||||
**Spring Aspects**
|
Spring5.x 版本中 Web 模块的 Portlet 组件已经被废弃掉,同时增加了用于异步响应式处理的 WebFlux 组件。
|
||||||
|
|
||||||
该模块为与 AspectJ 的集成提供支持。
|
Spring 各个模块的依赖关系如下:
|
||||||
|
|
||||||
**Spring AOP**
|

|
||||||
|
|
||||||
提供了面向切面的编程实现。
|
#### Core Container
|
||||||
|
|
||||||
**Spring Data Access/Integration :**
|
Spring 框架的核心模块,也可以说是基础模块,主要提供 IoC 依赖注入功能的支持。Spring 其他所有的功能基本都需要依赖于该模块,我们从上面那张 Spring 各个模块的依赖关系图就可以看出来。
|
||||||
|
|
||||||
Spring Data Access/Integration 由 5 个模块组成:
|
- **spring-core** :Spring 框架基本的核心工具类。
|
||||||
|
- **spring-beans** :提供对 bean 的创建、配置和管理等功能的支持。
|
||||||
|
- **spring-context** :提供对国际化、事件传播、资源加载等功能的支持。
|
||||||
|
- **spring-expression** :提供对表达式语言(Spring Expression Language) SpEL 的支持,只依赖于 core 模块,不依赖于其他模块,可以单独使用。
|
||||||
|
|
||||||
- spring-jdbc : 提供了对数据库访问的抽象 JDBC。不同的数据库都有自己独立的 API 用于操作数据库,而 Java 程序只需要和 JDBC API 交互,这样就屏蔽了数据库的影响。
|
#### AOP
|
||||||
- spring-tx : 提供对事务的支持。
|
|
||||||
- spring-orm : 提供对 Hibernate 等 ORM 框架的支持。
|
|
||||||
- spring-oxm : 提供对 Castor 等 OXM 框架的支持。
|
|
||||||
- spring-jms : Java 消息服务。
|
|
||||||
|
|
||||||
**Spring Web**
|
- **spring-aspects** :该模块为与 AspectJ 的集成提供支持。
|
||||||
|
- **spring-aop** :提供了面向切面的编程实现。
|
||||||
|
- **spring-instrument** :提供了为 JVM 添加代理(agent)的功能。 具体来讲,它为 Tomcat 提供了一个织入代理,能够为 Tomcat 传递类文 件,就像这些文件是被类加载器加载的一样。没有理解也没关系,这个模块的使用场景非常有限。
|
||||||
|
|
||||||
Spring Web 由 4 个模块组成:
|
#### Data Access/Integration
|
||||||
|
|
||||||
- spring-web :对 Web 功能的实现提供一些最基础的支持。
|
- **spring-jdbc** :提供了对数据库访问的抽象 JDBC。不同的数据库都有自己独立的 API 用于操作数据库,而 Java 程序只需要和 JDBC API 交互,这样就屏蔽了数据库的影响。
|
||||||
- spring-webmvc : 提供对 Spring MVC 的实现。
|
- **spring-tx** :提供对事务的支持。
|
||||||
- spring-websocket : 提供了对 WebSocket 的支持,WebSocket 可以让客户端和服务端进行双向通信。
|
- **spring-orm** : 提供对 Hibernate、JPA 、iBatis 等 ORM 框架的支持。
|
||||||
- spring-webflux :提供对 WebFlux 的支持。WebFlux 是 Spring Framework 5.0 中引入的新的响应式框架。与 Spring MVC 不同,它不需要 Servlet API,是完全异步.
|
- **spring-oxm** :提供一个抽象层支撑 OXM(Object-to-XML-Mapping),例如:JAXB、Castor、XMLBeans、JiBX 和 XStream 等。
|
||||||
|
- **spring-jms** : 消息服务。自 Spring Framework 4.1 以后,它还提供了对 spring-messaging 模块的继承。
|
||||||
|
|
||||||
**Spring Test**
|
#### Spring Web
|
||||||
|
|
||||||
|
- **spring-web** :对 Web 功能的实现提供一些最基础的支持。
|
||||||
|
- **spring-webmvc** : 提供对 Spring MVC 的实现。
|
||||||
|
- **spring-websocket** : 提供了对 WebSocket 的支持,WebSocket 可以让客户端和服务端进行双向通信。
|
||||||
|
- **spring-webflux** :提供对 WebFlux 的支持。WebFlux 是 Spring Framework 5.0 中引入的新的响应式框架。与 Spring MVC 不同,它不需要 Servlet API,是完全异步。
|
||||||
|
|
||||||
|
#### Messaging
|
||||||
|
|
||||||
|
**spring-messaging** 是从 Spring4.0 开始新加入的一个模块,主要职责是为 Spring 框架集成一些基础的报文传送应用。
|
||||||
|
|
||||||
|
#### Spring Test
|
||||||
|
|
||||||
Spring 团队提倡测试驱动开发(TDD)。有了控制反转 (IoC)的帮助,单元测试和集成测试变得更简单。
|
Spring 团队提倡测试驱动开发(TDD)。有了控制反转 (IoC)的帮助,单元测试和集成测试变得更简单。
|
||||||
|
|
||||||
Spring 的测试模块对 JUnit(单元测试框架)、TestNG(类似 JUnit)、Mockito(主要用来 Mock 对象)、PowerMock(解决 Mockito 的问题比如无法模拟 final, static, private 方法)等等常用的测试框架支持的都比较好。
|
Spring 的测试模块对 JUnit(单元测试框架)、TestNG(类似 JUnit)、Mockito(主要用来 Mock 对象)、PowerMock(解决 Mockito 的问题比如无法模拟 final, static, private 方法)等等常用的测试框架支持的都比较好。
|
||||||
|
|
||||||
## Spring,Spring MVC,Spring Boot 之间什么关系?
|
### Spring,Spring MVC,Spring Boot 之间什么关系?
|
||||||
|
|
||||||
很多人对 Spring,Spring MVC,Spring Boot 这三者傻傻分不清楚!这里简单介绍一下这三者,其实很简单,没有什么高深的东西。
|
很多人对 Spring,Spring MVC,Spring Boot 这三者傻傻分不清楚!这里简单介绍一下这三者,其实很简单,没有什么高深的东西。
|
||||||
|
|
||||||
@ -93,7 +106,7 @@ Spring 旨在简化 J2EE 企业应用程序开发。Spring Boot 旨在简化 Spr
|
|||||||
|
|
||||||
Spring Boot 只是简化了配置,如果你需要构建 MVC 架构的 Web 程序,你还是需要使用 Spring MVC 作为 MVC 框架,只是说 Spring Boot 帮你简化了 Spring MVC 的很多配置,真正做到开箱即用!
|
Spring Boot 只是简化了配置,如果你需要构建 MVC 架构的 Web 程序,你还是需要使用 Spring MVC 作为 MVC 框架,只是说 Spring Boot 帮你简化了 Spring MVC 的很多配置,真正做到开箱即用!
|
||||||
|
|
||||||
## Spring IOC & AOP
|
## Spring IoC
|
||||||
|
|
||||||
### 谈谈自己对于 Spring IoC 的了解
|
### 谈谈自己对于 Spring IoC 的了解
|
||||||
|
|
||||||
@ -119,26 +132,6 @@ Spring 时代我们一般通过 XML 文件来配置 Bean,后来开发人员觉
|
|||||||
- [IoC 源码阅读](https://javadoop.com/post/spring-ioc)
|
- [IoC 源码阅读](https://javadoop.com/post/spring-ioc)
|
||||||
- [面试被问了几百遍的 IoC 和 AOP ,还在傻傻搞不清楚?](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247486938&idx=1&sn=c99ef0233f39a5ffc1b98c81e02dfcd4&chksm=cea24211f9d5cb07fa901183ba4d96187820713a72387788408040822ffb2ed575d28e953ce7&token=1736772241&lang=zh_CN#rd)
|
- [面试被问了几百遍的 IoC 和 AOP ,还在傻傻搞不清楚?](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247486938&idx=1&sn=c99ef0233f39a5ffc1b98c81e02dfcd4&chksm=cea24211f9d5cb07fa901183ba4d96187820713a72387788408040822ffb2ed575d28e953ce7&token=1736772241&lang=zh_CN#rd)
|
||||||
|
|
||||||
### 谈谈自己对于 AOP 的了解
|
|
||||||
|
|
||||||
AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
|
|
||||||
|
|
||||||
Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 **JDK Proxy**,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 **Cglib** 生成一个被代理对象的子类来作为代理,如下图所示:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
当然你也可以使用 **AspectJ** !Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 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 快很多。
|
|
||||||
|
|
||||||
## Spring Bean
|
|
||||||
|
|
||||||
### 什么是 Spring Bean?
|
### 什么是 Spring Bean?
|
||||||
|
|
||||||
简单来说,Bean 代指的就是那些被 IoC 容器所管理的对象。
|
简单来说,Bean 代指的就是那些被 IoC 容器所管理的对象。
|
||||||
@ -287,11 +280,12 @@ private SmsService smsService;
|
|||||||
|
|
||||||
Spring 中 Bean 的作用域通常有下面几种:
|
Spring 中 Bean 的作用域通常有下面几种:
|
||||||
|
|
||||||
- **singleton** : 唯一 bean 实例,Spring 中的 bean 默认都是单例的,对单例设计模式的应用。
|
- **singleton** : IoC 容器中只有唯一的 bean 实例。Spring 中的 bean 默认都是单例的,是对单例设计模式的应用。
|
||||||
- **prototype** : 每次请求都会创建一个新的 bean 实例。
|
- **prototype** : 每次获取都会创建一个新的 bean 实例。也就是说,连续 `getBean()` 两次,得到的是不同的 Bean 实例。
|
||||||
- **request** : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。
|
- **request** (仅 Web 应用可用): 每一次 HTTP 请求都会产生一个新的 bean(请求 bean),该 bean 仅在当前 HTTP request 内有效。
|
||||||
- **session** : 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。
|
- **session** (仅 Web 应用可用) : 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean(会话 bean),该 bean 仅在当前 HTTP session 内有效。
|
||||||
- **global-session** : 全局 session 作用域,仅仅在基于 portlet 的 web 应用中才有意义,Spring5 已经没有了。Portlet 是能够生成语义代码(例如:HTML)片段的小型 Java Web 插件。它们基于 portlet 容器,可以像 servlet 一样处理 HTTP 请求。但是,与 servlet 不同,每个 portlet 都有不同的会话。
|
- **application/global-session** (仅 Web 应用可用): 每个 Web 应用在启动时创建一个 Bean(应用 Bean),,该 bean 仅在当前应用启动时间内有效。
|
||||||
|
- **websocket** (仅 Web 应用可用):每一次 WebSocket 会话产生一个新的 bean。
|
||||||
|
|
||||||
**如何配置 bean 的作用域呢?**
|
**如何配置 bean 的作用域呢?**
|
||||||
|
|
||||||
@ -348,6 +342,75 @@ public Person personPrototype() {
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## Spring AoP
|
||||||
|
|
||||||
|
### 谈谈自己对于 AOP 的了解
|
||||||
|
|
||||||
|
AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
|
||||||
|
|
||||||
|
Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 **JDK Proxy**,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 **Cglib** 生成一个被代理对象的子类来作为代理,如下图所示:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
当然你也可以使用 **AspectJ** !Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。
|
||||||
|
|
||||||
|
AOP 切面编程设计到的一些专业术语:
|
||||||
|
|
||||||
|
| 术语 | 含义 |
|
||||||
|
| :---------------- | :----------------------------------------------------------: |
|
||||||
|
| 目标(Target) | 被通知的对象 |
|
||||||
|
| 代理(Proxy) | 向目标对象应用通知之后创建的代理对象 |
|
||||||
|
| 连接点(JoinPoint) | 目标对象的所属类中,定义的所有方法均为连接点 |
|
||||||
|
| 切入点(Pointcut) | 被切面拦截 / 增强的连接点(切入点一定是连接点,连接点不一定是切入点) |
|
||||||
|
| 通知(Advice) | 增强的逻辑 / 代码,也即拦截到目标对象的连接点之后要做的事情 |
|
||||||
|
| 切面(Aspect) | 切入点(Pointcut)+通知(Advice) |
|
||||||
|
| Weaving(织入) | 将通知应用到目标对象,进而生成代理对象的过程动作 |
|
||||||
|
|
||||||
|
### 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 快很多。
|
||||||
|
|
||||||
|
### AspectJ 定义的通知类型有哪些?
|
||||||
|
|
||||||
|
- **Before**(前置通知):目标对象的方法调用之前触发
|
||||||
|
- **After** (后置通知):目标对象的方法调用之后触发
|
||||||
|
- **AfterReturning**(返回通知):目标对象的方法调用完成,在返回结果值之后触发
|
||||||
|
- **AfterThrowing**(异常通知) :目标对象的方法运行中抛出 / 触发异常后触发。AfterReturning 和 AfterThrowing 两者互斥。如果方法调用成功无异常,则会有返回值;如果方法抛出了异常,则不会有返回值。
|
||||||
|
- **Around**: (环绕通知)编程式控制目标对象的方法调用。环绕通知是所有通知类型中可操作范围最大的一种,因为它可以直接拿到目标对象,以及要执行的方法,所以环绕通知可以任意的在目标对象的方法调用前后搞事,甚至不调用目标对象的方法
|
||||||
|
|
||||||
|
### 多个切面的执行顺序如何控制?
|
||||||
|
|
||||||
|
1、通常使用`@Order` 注解直接定义切面顺序
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 值越小优先级越高
|
||||||
|
@Order(3)
|
||||||
|
@Component
|
||||||
|
@Aspect
|
||||||
|
public class LoggingAspect implements Ordered {
|
||||||
|
```
|
||||||
|
|
||||||
|
**2、实现`Ordered` 接口重写 `getOrder` 方法。**
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Component
|
||||||
|
@Aspect
|
||||||
|
public class LoggingAspect implements Ordered {
|
||||||
|
|
||||||
|
// ....
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
// 返回值越小优先级越高
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Spring MVC
|
## Spring MVC
|
||||||
|
|
||||||
### 说说自己对于 Spring MVC 了解?
|
### 说说自己对于 Spring MVC 了解?
|
||||||
@ -390,6 +453,16 @@ Model2 模式下还存在很多问题,Model2 的抽象和封装程度还远远
|
|||||||
|
|
||||||
MVC 是一种设计模式,Spring MVC 是一款很优秀的 MVC 框架。Spring MVC 可以帮助我们进行更简洁的 Web 层的开发,并且它天生与 Spring 框架集成。Spring MVC 下我们一般把后端项目分为 Service 层(处理业务)、Dao 层(数据库操作)、Entity 层(实体类)、Controller 层(控制层,返回数据给前台页面)。
|
MVC 是一种设计模式,Spring MVC 是一款很优秀的 MVC 框架。Spring MVC 可以帮助我们进行更简洁的 Web 层的开发,并且它天生与 Spring 框架集成。Spring MVC 下我们一般把后端项目分为 Service 层(处理业务)、Dao 层(数据库操作)、Entity 层(实体类)、Controller 层(控制层,返回数据给前台页面)。
|
||||||
|
|
||||||
|
### Spring MVC 的核心组件有哪些?
|
||||||
|
|
||||||
|
记住了下面这些组件,也就记住了 SpringMVC 的工作原理。
|
||||||
|
|
||||||
|
- **`DispatcherServlet`** :**核心的中央处理器**,负责接收请求、分发,并给予客户端响应。
|
||||||
|
- **`HandlerMapping`** :**处理器映射器**,根据 uri 去匹配查找能处理的 `Handler` ,并会将请求涉及到的拦截器和 `Handler` 一起封装。
|
||||||
|
- **`HandlerAdapter`** :**处理器适配器**,根据 `HandlerMapping` 找到的 `Handler` ,适配执行对应的 `Handler`;
|
||||||
|
- **`Handler`** :**请求处理器**,处理实际请求的处理器。
|
||||||
|
- **`ViewResolver`** :**视图解析器**,根据 `Handler` 返回的逻辑视图 / 视图,解析并渲染真正的视图,并传递给 `DispatcherServlet` 响应客户端
|
||||||
|
|
||||||
### SpringMVC 工作原理了解吗?
|
### SpringMVC 工作原理了解吗?
|
||||||
|
|
||||||
**Spring MVC 原理如下图所示:**
|
**Spring MVC 原理如下图所示:**
|
||||||
@ -400,14 +473,63 @@ MVC 是一种设计模式,Spring MVC 是一款很优秀的 MVC 框架。Spring
|
|||||||
|
|
||||||
**流程说明(重要):**
|
**流程说明(重要):**
|
||||||
|
|
||||||
1. 客户端(浏览器)发送请求,直接请求到 `DispatcherServlet`。
|
1. 客户端(浏览器)发送请求, `DispatcherServlet`拦截请求。
|
||||||
2. `DispatcherServlet` 根据请求信息调用 `HandlerMapping`,解析请求对应的 `Handler`。
|
2. `DispatcherServlet` 根据请求信息调用 `HandlerMapping` 。`HandlerMapping` 根据 uri 去匹配查找能处理的 `Handler`(也就是我们平常说的 `Controller` 控制器) ,并会将请求涉及到的拦截器和 `Handler` 一起封装。
|
||||||
3. 解析到对应的 `Handler`(也就是我们平常说的 `Controller` 控制器)后,开始由 `HandlerAdapter` 适配器处理。
|
3. `DispatcherServlet` 调用 `HandlerAdapter`适配执行 `Handler` 。
|
||||||
4. `HandlerAdapter` 会根据 `Handler`来调用真正的处理器开处理请求,并处理相应的业务逻辑。
|
4. `Handler` 完成对用户请求的处理后,会返回一个 `ModelAndView` 对象给`DispatcherServlet`,`ModelAndView` 顾名思义,包含了数据模型以及相应的视图的信息。`Model` 是返回的数据对象,`View` 是个逻辑上的 `View`。
|
||||||
5. 处理器处理完业务后,会返回一个 `ModelAndView` 对象,`Model` 是返回的数据对象,`View` 是个逻辑上的 `View`。
|
5. `ViewResolver` 会根据逻辑 `View` 查找实际的 `View`。
|
||||||
6. `ViewResolver` 会根据逻辑 `View` 查找实际的 `View`。
|
6. `DispaterServlet` 把返回的 `Model` 传给 `View`(视图渲染)。
|
||||||
7. `DispaterServlet` 把返回的 `Model` 传给 `View`(视图渲染)。
|
7. 把 `View` 返回给请求者(浏览器)
|
||||||
8. 把 `View` 返回给请求者(浏览器)
|
|
||||||
|
### 统一异常处理怎么做?
|
||||||
|
|
||||||
|
推荐使用注解的方式统一异常处理,具体会使用到 `@ControllerAdvice` + `@ExceptionHandler` 这两个注解 。
|
||||||
|
|
||||||
|
```java
|
||||||
|
@ControllerAdvice
|
||||||
|
@ResponseBody
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
@ExceptionHandler(BaseException.class)
|
||||||
|
public ResponseEntity<?> handleAppException(BaseException ex, HttpServletRequest request) {
|
||||||
|
//......
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(value = ResourceNotFoundException.class)
|
||||||
|
public ResponseEntity<ErrorReponse> handleResourceNotFoundException(ResourceNotFoundException ex, HttpServletRequest request) {
|
||||||
|
//......
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
这种异常处理方式下,会给所有或者指定的 `Controller` 织入异常处理的逻辑(AOP),当 `Controller` 中的方法抛出异常的时候,由被`@ExceptionHandler` 注解修饰的方法进行处理。
|
||||||
|
|
||||||
|
`ExceptionHandlerMethodResolver` 中 `getMappedMethod` 方法决定了异常具体被哪个被 `@ExceptionHandler` 注解修饰的方法处理异常。
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Nullable
|
||||||
|
private Method getMappedMethod(Class<? extends Throwable> exceptionType) {
|
||||||
|
List<Class<? extends Throwable>> matches = new ArrayList<>();
|
||||||
|
//找到可以处理的所有异常信息。mappedMethods 中存放了异常和处理异常的方法的对应关系
|
||||||
|
for (Class<? extends Throwable> mappedException : this.mappedMethods.keySet()) {
|
||||||
|
if (mappedException.isAssignableFrom(exceptionType)) {
|
||||||
|
matches.add(mappedException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 不为空说明有方法处理异常
|
||||||
|
if (!matches.isEmpty()) {
|
||||||
|
// 按照匹配程度从小到大排序
|
||||||
|
matches.sort(new ExceptionDepthComparator(exceptionType));
|
||||||
|
// 返回处理异常的方法
|
||||||
|
return this.mappedMethods.get(matches.get(0));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
从源代码看出:**`getMappedMethod()`会首先找到可以匹配处理异常的所有方法信息,然后对其进行从小到大的排序,最后取最小的那一个匹配的方法(即匹配度最高的那个)。**
|
||||||
|
|
||||||
## Spring 框架中用到了哪些设计模式?
|
## Spring 框架中用到了哪些设计模式?
|
||||||
|
|
||||||
@ -550,6 +672,7 @@ String transient4; // not persistent because of @Transient
|
|||||||
## 参考
|
## 参考
|
||||||
|
|
||||||
- 《Spring 技术内幕》
|
- 《Spring 技术内幕》
|
||||||
|
- 《从零开始深入学习 Spring》:https://juejin.cn/book/6857911863016390663
|
||||||
- <http://www.cnblogs.com/wmyskxz/p/8820371.html>
|
- <http://www.cnblogs.com/wmyskxz/p/8820371.html>
|
||||||
- <https://www.journaldev.com/2696/spring-interview-questions-and-answers>
|
- <https://www.journaldev.com/2696/spring-interview-questions-and-answers>
|
||||||
- <https://www.edureka.co/blog/interview-questions/spring-interview-questions/>
|
- <https://www.edureka.co/blog/interview-questions/spring-interview-questions/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user