Skip to content

Commit

Permalink
add spring/3
Browse files Browse the repository at this point in the history
  • Loading branch information
deepraining committed Oct 14, 2021
1 parent 55a2f3b commit d247ff3
Show file tree
Hide file tree
Showing 4 changed files with 1,995 additions and 106 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## Spring 源码解析

1. [\[2021-10-09\] SpringMVC 的加载机制](spring/1.md)
1. [\[2021-10-12\] Spring 源码解析二:SpringMVC 的上下文组件(WebApplicationContext)](spring/2.md)
1. [\[2021-10-14\] Spring 源码解析三:SpringMVC 的 Bean 注册、解析、实例化机制](spring/3.md)

## 前端进阶

Expand Down
63 changes: 40 additions & 23 deletions spring/1.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ SpringMVC 框架的核心模块主要是:`spring-core`、`spring-beans`、`spr
Spring bean 的加载与扩展机制有几点需要在这里简单介绍一下:

1. Spring bean 的定义主要是两种:基于注解的定义、基于 XML 文件的定义
1. `spring-beans` 提供了基于 XML 配置的、第三方对 bean 的自定义扩展机制,主要是在 `META-INF/spring.handlers, META-INF/spring.schemas` 文件中定义需要扩展的标签,比如 `<dubbo:application name="name"/>, <dubbo:registry address="address"/>`
1. `spring-beans` 提供了基于 XML 配置的、第三方对 bean 的自定义扩展机制,主要是在
`META-INF/spring.handlers, META-INF/spring.schemas` 文件中定义需要扩展的标签,
比如 `<dubbo:application name="name"/>, <dubbo:registry address="address"/>`
1. 基于注解的自定义扩展,需要依赖 `spring-boot` 的扩展加载机制

### 1.3. `spring-context`
Expand Down Expand Up @@ -90,9 +92,11 @@ Spring bean 的加载与扩展机制有几点需要在这里简单介绍一下

### 1.6. `spring-webflux`

`spring-webflux``spring-webmvc` 相对应,`webmvc` 是同步阻塞框架,而 `webflux` 是异步非阻塞框架,是 Spring Framework 5.0 中引入的新的响应式 web 框架。
`spring-webflux``spring-webmvc` 相对应,`webmvc` 是同步阻塞框架,而 `webflux` 是异步非阻塞框架,
是 Spring Framework 5.0 中引入的新的响应式 web 框架。

参考:[Spring WebFlux 入门](https://www.cnblogs.com/cjsblog/archive/2020/03/27/12580518.html)[Spring WebFlux :: Spring Docs](https://spring.getdocs.org/en-US/spring-framework-docs/docs/spring-web-reactive/webflux/webflux.html)
参考:[Spring WebFlux 入门](https://www.cnblogs.com/cjsblog/archive/2020/03/27/12580518.html)
[Spring WebFlux :: Spring Docs](https://spring.getdocs.org/en-US/spring-framework-docs/docs/spring-web-reactive/webflux/webflux.html)

## 2. 一个简单的 `spring-webmvc` 项目配置

Expand Down Expand Up @@ -134,8 +138,10 @@ Spring bean 的加载与扩展机制有几点需要在这里简单介绍一下

这里有两个入口类:

- `servlet-class` [org.springframework.web.servlet.DispatcherServlet](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java): 指定用来处理对应 URL 请求的类
- `listener-class` [org.springframework.web.context.ContextLoaderListener](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/ContextLoaderListener.java): 设置事件监听器,事件监听程序在建立、修改和删除会话或 servlet 环境时得到通知
- `servlet-class` [org.springframework.web.servlet.DispatcherServlet](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java)
: 指定用来处理对应 URL 请求的类
- `listener-class` [org.springframework.web.context.ContextLoaderListener](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/ContextLoaderListener.java)
: 设置事件监听器,事件监听程序在建立、修改和删除会话或 servlet 环境时得到通知

这两个类分别定义在 `spring-webmvc``spring-web` 中,下面对他们一一进行解析。

Expand Down Expand Up @@ -342,7 +348,7 @@ public abstract class HttpServletBean extends HttpServlet implements Environment
// 初始化
@Override
public final void init() throws ServletException {
// Set bean properties from init parameters.
// 把Servlet配置参数设置到bean属性中
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
if (!pvs.isEmpty()) {
try {
Expand All @@ -360,7 +366,7 @@ public abstract class HttpServletBean extends HttpServlet implements Environment
}
}

// Let subclasses do whatever initialization they like.
// 初始化Servlet bean
initServletBean();
}

Expand Down Expand Up @@ -389,7 +395,8 @@ public abstract class HttpServletBean extends HttpServlet implements Environment

#### 3.5.1. FrameworkServlet.initServletBean

父类 `HttpServletBean` 初始化后,留下两个钩子 `initBeanWrapper, initServletBean``initBeanWrapper` 默认并不实现,所以来看看 `initServletBean` 钩子的实现:[FrameworkServlet.initServletBean](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java#L522)
父类 `HttpServletBean` 初始化后,留下两个钩子 `initBeanWrapper, initServletBean``initBeanWrapper` 默认并不实现,
所以来看看 `initServletBean` 钩子的实现:[FrameworkServlet.initServletBean](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java#L522)

```java
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
Expand Down Expand Up @@ -427,7 +434,7 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
WebApplicationContext wac = null;

if (this.webApplicationContext != null) {
// A context instance was injected at construction time -> use it
// 对webApplicationContext进行配置
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
Expand Down Expand Up @@ -593,7 +600,6 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
// 扩展处理
processRequest(request, response);
if (response.containsHeader("Allow")) {
// Proper OPTIONS response coming from a handler - we're done.
return;
}
}
Expand All @@ -609,7 +615,6 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
// 扩展处理
processRequest(request, response);
if ("message/http".equals(response.getContentType())) {
// Proper TRACE response coming from a handler - we're done.
return;
}
}
Expand Down Expand Up @@ -662,7 +667,8 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic

### 3.6. DispatcherServlet

`DispatcherServlet` 主要扩展了 2 个方法:`onRefresh``doService`,所以来看看 [DispatcherServlet](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java) 是如何实现的
`DispatcherServlet` 主要扩展了 2 个方法:`onRefresh``doService`,所以来看看 [DispatcherServlet](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java)
是如何实现的

#### 3.6.1. DispatcherServlet.onRefresh

Expand Down Expand Up @@ -827,7 +833,8 @@ public class DispatcherServlet extends FrameworkServlet {
}
```

[DispatcherServlet.properties](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/resources/org/springframework/web/servlet/DispatcherServlet.properties) 文件(开发者不能自定义覆盖)如下:
[DispatcherServlet.properties](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/resources/org/springframework/web/servlet/DispatcherServlet.properties)
文件(开发者不能自定义覆盖)如下:

```properties
# Default implementation classes for DispatcherServlet's strategy interfaces.
Expand Down Expand Up @@ -1154,10 +1161,14 @@ public class DispatcherServlet extends FrameworkServlet {

`DispatcherServlet` 这个类的解析基本上就差不多了,但还有几点没有解析:

- [FrameworkServlet(L702)](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java#L702): `ConfigurableWebApplicationContext.refresh`
- [DispatcherServlet(L514)](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java#L514): `ApplicationContext.getBean`
- [DispatcherServlet.properties](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/resources/org/springframework/web/servlet/DispatcherServlet.properties) 文件中定义的策略处理
- [DispatcherServlet(L1393)](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java#L1393): `View.render`
- [FrameworkServlet(L702)](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java#L702)
: `ConfigurableWebApplicationContext.refresh`
- [DispatcherServlet(L514)](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java#L514)
: `ApplicationContext.getBean`
- [DispatcherServlet.properties](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/resources/org/springframework/web/servlet/DispatcherServlet.properties)
文件中定义的策略处理
- [DispatcherServlet(L1393)](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java#L1393)
: `View.render`

这几点,我们后面再来解析。

Expand All @@ -1170,7 +1181,8 @@ public class DispatcherServlet extends FrameworkServlet {
- ContextLoaderListener
```

[ContextLoaderListener](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/ContextLoaderListener.java) 比较简单,只有两个监听事件方法
[ContextLoaderListener](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/ContextLoaderListener.java)
比较简单,只有两个监听事件方法

```java
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
Expand All @@ -1190,7 +1202,8 @@ public class ContextLoaderListener extends ContextLoader implements ServletConte
}
```

[ContextLoader](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/ContextLoader.java) 的静态初始化
[ContextLoader](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/ContextLoader.java)
的静态初始化

```java
public class ContextLoader {
Expand All @@ -1207,7 +1220,8 @@ public class ContextLoader {
}
```

[ContextLoader.properties](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/resources/org/springframework/web/context/ContextLoader.properties) 文件的内容如下:
[ContextLoader.properties](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/resources/org/springframework/web/context/ContextLoader.properties)
文件的内容如下:

```properties
# Default WebApplicationContext implementation class for ContextLoader.
Expand All @@ -1219,7 +1233,8 @@ org.springframework.web.context.WebApplicationContext=org.springframework.web.co

`ContextLoader.properties` 文件中指明使用 `XmlWebApplicationContext` 作为默认的 Web 应用上下文环境

再来看看 [ContextLoader](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/ContextLoader.java)`initWebApplicationContext``closeWebApplicationContext`
再来看看 [ContextLoader](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/ContextLoader.java)
`initWebApplicationContext``closeWebApplicationContext`

### 4.1. ContextLoaderListener.initWebApplicationContext

Expand Down Expand Up @@ -1264,7 +1279,8 @@ public class ContextLoader {
}
```

`ContextLoader.configureAndRefreshWebApplicationContext``FrameworkServlet.configureAndRefreshWebApplicationContext` 的处理基本上一致。
`ContextLoader.configureAndRefreshWebApplicationContext``FrameworkServlet.configureAndRefreshWebApplicationContext`
的处理基本上一致。

也就是说,当容器启动(如 Tomcat、Jetty、Undertow 等)时,Spring 框架会自动进行初始化。

Expand Down Expand Up @@ -1294,7 +1310,8 @@ public class ContextLoader {

1. 初始化 Web 应用上下文,默认使用 `XmlWebApplicationContext`(基于 XML 加载)作为应用上下文,并调用 `refresh` 方法
1. 实例化由 `globalInitializerClasses``contextInitializerClasses` 定义的类
1. 实例化 WebMVC 必要的组件:`MultipartResolver`, `LocaleResolver`, `ThemeResolver`, `HandlerMapping`, `HandlerAdapter`, `HandlerExceptionResolver`, `RequestToViewNameTranslator`, `ViewResolver`, `FlashMapManager`
1. 实例化 WebMVC 必要的组件:`MultipartResolver`, `LocaleResolver`, `ThemeResolver`, `HandlerMapping`,
`HandlerAdapter`, `HandlerExceptionResolver`, `RequestToViewNameTranslator`, `ViewResolver`, `FlashMapManager`

每个请求都会进入到 `DispatcherServlet.service`,其主要过程是:

Expand Down
Loading

0 comments on commit d247ff3

Please sign in to comment.