diff --git a/README.md b/README.md
index 1393abe..a4aa1c9 100644
--- a/README.md
+++ b/README.md
@@ -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)
## 前端进阶
diff --git a/spring/1.md b/spring/1.md
index 872ba03..3e0889f 100644
--- a/spring/1.md
+++ b/spring/1.md
@@ -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` 文件中定义需要扩展的标签,比如 `, `
+1. `spring-beans` 提供了基于 XML 配置的、第三方对 bean 的自定义扩展机制,主要是在
+ `META-INF/spring.handlers, META-INF/spring.schemas` 文件中定义需要扩展的标签,
+ 比如 `, `
1. 基于注解的自定义扩展,需要依赖 `spring-boot` 的扩展加载机制
### 1.3. `spring-context`
@@ -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` 项目配置
@@ -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` 中,下面对他们一一进行解析。
@@ -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 {
@@ -360,7 +366,7 @@ public abstract class HttpServletBean extends HttpServlet implements Environment
}
}
- // Let subclasses do whatever initialization they like.
+ // 初始化Servlet bean
initServletBean();
}
@@ -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 {
@@ -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;
@@ -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;
}
}
@@ -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;
}
}
@@ -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
@@ -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.
@@ -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`
这几点,我们后面再来解析。
@@ -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 {
@@ -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 {
@@ -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.
@@ -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
@@ -1264,7 +1279,8 @@ public class ContextLoader {
}
```
-`ContextLoader.configureAndRefreshWebApplicationContext` 与 `FrameworkServlet.configureAndRefreshWebApplicationContext` 的处理基本上一致。
+`ContextLoader.configureAndRefreshWebApplicationContext` 与 `FrameworkServlet.configureAndRefreshWebApplicationContext`
+的处理基本上一致。
也就是说,当容器启动(如 Tomcat、Jetty、Undertow 等)时,Spring 框架会自动进行初始化。
@@ -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`,其主要过程是:
diff --git a/spring/2.md b/spring/2.md
index 74e9e66..9ae4b19 100644
--- a/spring/2.md
+++ b/spring/2.md
@@ -1,6 +1,6 @@
# Spring 源码解析二:SpringMVC 的上下文组件(WebApplicationContext)
-上一篇分析 `DispatcherServlet` 与 `ContextLoaderListener` 这两个类,分析了应用初始化与请求处理的流程,但还有一些组件需要分析:
+上一篇分析了 `DispatcherServlet` 与 `ContextLoaderListener` 这两个类,分析了应用初始化与请求处理的流程,但还有一些组件需要分析:
- `ConfigurableWebApplicationContext.refresh` 刷新上下文
- `ApplicationContext.getBean` 从上下文中获取 bean
@@ -20,58 +20,66 @@ org.springframework.web.context.WebApplicationContext=org.springframework.web.co
`spring-web` 内部定义 5 个应用上下文类:
-- [GenericWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/GenericWebApplicationContext.java):`WebApplicationContext`的基础实现,但不能通过配置文件和注解加载应用配置与 bean,很少用到
-- [StaticWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/StaticWebApplicationContext.java):也是`WebApplicationContext`的基础实现,但不支持 i18n,主要用于测试,不用产品环境
-- [XmlWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/XmlWebApplicationContext.java):基于 XML 加载应用配置与 bean 的`WebApplicationContext`实现,是 SpringMVC 的默认 Context
-- [AnnotationConfigWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java):基于注解如 `@Configuration, @bean` 等加载应用配置与 bean 的`WebApplicationContext`实现,是 SpringBoot 的基础
-- [GroovyWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/GroovyWebApplicationContext.java):与`XmlWebApplicationContext`的实现差不多,但可以用 Groovy 代替 xml 做配置文件,目前用得不多
+- [GenericWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/GenericWebApplicationContext.java)
+ :`WebApplicationContext`的基础实现,但不能通过配置文件和注解加载应用配置与 bean,很少用到
+- [StaticWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/StaticWebApplicationContext.java)
+ :也是`WebApplicationContext`的基础实现,但不支持 i18n,主要用于测试,不用产品环境
+- [XmlWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/XmlWebApplicationContext.java)
+ :基于 XML 加载应用配置与 bean 的`WebApplicationContext`实现,是 SpringMVC 的默认 Context
+- [AnnotationConfigWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java)
+ :基于注解如 `@Configuration, @bean` 等加载应用配置与 bean 的`WebApplicationContext`实现,是 SpringBoot 的基础
+- [GroovyWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/GroovyWebApplicationContext.java)
+ :与`XmlWebApplicationContext`的实现差不多,但可以用 Groovy 代替 xml 做配置文件,目前用得不多
先来看看这 5 个应用上下文类各自的继承关系
```
-- ResourceLoader
- - DefaultResourceLoader
- - AbstractApplicationContext
- - GenericApplicationContext
- - GenericWebApplicationContext
-
-- ResourceLoader
- - DefaultResourceLoader
- - AbstractApplicationContext
- - GenericApplicationContext
- - StaticApplicationContext
- - StaticWebApplicationContext
-
-- ResourceLoader
- - DefaultResourceLoader
- - AbstractApplicationContext
- - AbstractRefreshableApplicationContext
- - AbstractRefreshableConfigApplicationContext
- - AbstractRefreshableWebApplicationContext
- - XmlWebApplicationContext
-
-- ResourceLoader
- - DefaultResourceLoader
- - AbstractApplicationContext
- - AbstractRefreshableApplicationContext
- - AbstractRefreshableConfigApplicationContext
- - AbstractRefreshableWebApplicationContext
- - AnnotationConfigWebApplicationContext
-
-- ResourceLoader
- - DefaultResourceLoader
- - AbstractApplicationContext
- - AbstractRefreshableApplicationContext
- - AbstractRefreshableConfigApplicationContext
- - AbstractRefreshableWebApplicationContext
- - GroovyWebApplicationContext
+- DefaultResourceLoader
+ - AbstractApplicationContext
+ - GenericApplicationContext
+ - GenericWebApplicationContext
+
+- DefaultResourceLoader
+ - AbstractApplicationContext
+ - GenericApplicationContext
+ - StaticApplicationContext
+ - StaticWebApplicationContext
+
+- DefaultResourceLoader
+ - AbstractApplicationContext
+ - AbstractRefreshableApplicationContext
+ - AbstractRefreshableConfigApplicationContext
+ - AbstractRefreshableWebApplicationContext
+ - XmlWebApplicationContext
+
+- DefaultResourceLoader
+ - AbstractApplicationContext
+ - AbstractRefreshableApplicationContext
+ - AbstractRefreshableConfigApplicationContext
+ - AbstractRefreshableWebApplicationContext
+ - AnnotationConfigWebApplicationContext
+
+- DefaultResourceLoader
+ - AbstractApplicationContext
+ - AbstractRefreshableApplicationContext
+ - AbstractRefreshableConfigApplicationContext
+ - AbstractRefreshableWebApplicationContext
+ - GroovyWebApplicationContext
```
-我们可以发现每个类都继承 `AbstractApplicationContext`,而 `XmlWebApplicationContext, AnnotationConfigWebApplicationContext, GroovyWebApplicationContext` 都继承 `AbstractRefreshableWebApplicationContext`
+我们可以发现每个类都继承 `AbstractApplicationContext`,而 `XmlWebApplicationContext`, `AnnotationConfigWebApplicationContext`,
+`GroovyWebApplicationContext` 都继承 `AbstractRefreshableWebApplicationContext`
-## 1. ResourceLoader
+## 1. DefaultResourceLoader
-[ResourceLoader](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-core/src/main/java/org/springframework/core/io/ResourceLoader.java)
+[DefaultResourceLoader](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-core/src/main/java/org/springframework/core/io/DefaultResourceLoader.java)
+的主要功能是实现资源加载
+
+```java
+public class DefaultResourceLoader implements ResourceLoader {}
+```
+
+先来看看接口[ResourceLoader](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-core/src/main/java/org/springframework/core/io/ResourceLoader.java)
```java
public interface ResourceLoader {
@@ -83,9 +91,8 @@ public interface ResourceLoader {
}
```
-## 2. DefaultResourceLoader
-
[DefaultResourceLoader](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-core/src/main/java/org/springframework/core/io/DefaultResourceLoader.java)
+是 `ResourceLoader` 的默认实现
```java
public class DefaultResourceLoader implements ResourceLoader {
@@ -128,16 +135,18 @@ public class DefaultResourceLoader implements ResourceLoader {
}
```
-## 3. AbstractApplicationContext
+## 2. AbstractApplicationContext
[AbstractApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java)
+的主要功能是通过名字、类型或注解获取 bean 实例,获取上下文的环境对象与资源、刷新上下文数据
```java
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {}
```
-而 [ConfigurableApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/ConfigurableApplicationContext.java) 及其继承的接口主要定义以下的接口
+接口 [ConfigurableApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/ConfigurableApplicationContext.java)
+及其继承的接口主要定义以下的方法
```java
public interface ConfigurableApplicationContext {
@@ -165,9 +174,10 @@ public interface ConfigurableApplicationContext {
}
```
-### 3.1. AbstractApplicationContext.getEnvironment
+### 2.1. AbstractApplicationContext.getEnvironment
[AbstractApplicationContext.getEnvironment](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L339)
+获取环境
```java
public abstract class AbstractApplicationContext extends DefaultResourceLoader
@@ -182,16 +192,17 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
protected ConfigurableEnvironment createEnvironment() {
// 内置的标准环境(也可以通过setEnvironment方法自定义环境处理机制)
- // 这里可以使用 `application-dev.yml, application-test.yml, application-prod.yml, ...` 来根据环境加载不同的配置的底层实现
+ // 这是可以使用 `application-dev.yml, application-test.yml, application-prod.yml, ...` 来根据环境加载不同的配置的底层实现
// 是spring-boot的基本功能
return new StandardEnvironment();
}
}
```
-### 3.2. AbstractApplicationContext.getBean
+### 2.2. AbstractApplicationContext.getBean
[AbstractApplicationContext.getBean](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L1157)
+获取 bean
```java
public abstract class AbstractApplicationContext extends DefaultResourceLoader
@@ -228,9 +239,10 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
因为不同的`Context`注册 bean 的方式不一样,所以`getBeanFactory`留给子类来实现
-### 3.3. AbstractApplicationContext.getBeansOfType
+### 2.3. AbstractApplicationContext.getBeansOfType
[AbstractApplicationContext.getBeansOfType](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L1303)
+通过类型或注解获取 bean
```java
public abstract class AbstractApplicationContext extends DefaultResourceLoader
@@ -257,9 +269,10 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
}
```
-### 3.4. AbstractApplicationContext.refresh
+### 2.4. AbstractApplicationContext.refresh
[AbstractApplicationContext.refresh](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L550)
+刷新上下文数据
```java
public abstract class AbstractApplicationContext extends DefaultResourceLoader
@@ -368,9 +381,10 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
- 因为不同的`Context`注册 bean 的方式不一样,所以`refreshBeanFactory, postProcessBeanFactory`留给子类来实现
- `ConfigurableListableBeanFactory`如何加载、实例化 bean,后面再解析
-### 3.5. AbstractApplicationContext.prepareBeanFactory
+### 2.5. AbstractApplicationContext.prepareBeanFactory
[AbstractApplicationContext.prepareBeanFactory](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L685)
+预备 bean 工厂
```java
public abstract class AbstractApplicationContext extends DefaultResourceLoader
@@ -386,7 +400,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
// 添加属性编辑器,xml、yaml 中定义的值转换成对象就是依赖这里实现的
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
- // Configure the bean factory with context callbacks.
+ // 添加一个BeanPostProcessor,后置处理器
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// ... 代码省略
@@ -418,9 +432,10 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
- `ResourceEditorRegistrar`如何注册属性编辑器、属性编辑器如何解析为对象,后面再解析
-### 3.6. AbstractApplicationContext.getResources
+### 2.6. AbstractApplicationContext.getResources
[AbstractApplicationContext.getResources](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L1415)
+根据 locationPattern 获取多个资源,如通配符\*
```java
public abstract class AbstractApplicationContext extends DefaultResourceLoader
@@ -444,20 +459,22 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
- `PathMatchingResourcePatternResolver`如何解析、加载 locationPattern 指定的资源,后面再解析
-### 3.7. 综述
+### 2.7. 综述
总的来说,`AbstractApplicationContext` 类完成上下文环境的大部分功能,包括环境加载、bean 的加载与前置后置处理、事件派发、完成一些初始化工作等,
但扩展了几个接口给子类实现,如如何加载、注册、实例化 bean 等
-## 4. GenericApplicationContext
+## 3. GenericApplicationContext
[GenericApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/support/GenericApplicationContext.java)
+的主要功能是注册、管理 bean 的定义与别名
```java
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {}
```
-[BeanDefinitionRegistry](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionRegistry.java) 这个接口主要定义了注册 bean 的定义及别名
+[BeanDefinitionRegistry](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionRegistry.java)
+这个接口主要定义了注册 bean 的定义及别名
```java
public interface BeanDefinitionRegistry {
@@ -528,9 +545,10 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
最终还是落脚在 `beanFactory` 上
-## 5. GenericWebApplicationContext
+## 4. GenericWebApplicationContext
[GenericWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/GenericWebApplicationContext.java)
+的主要功能是添加了设置 bean 配置文件来源,允许通过配置的方式实例化上下文环境
```java
public class GenericWebApplicationContext extends GenericApplicationContext
@@ -589,11 +607,13 @@ public class GenericWebApplicationContext extends GenericApplicationContext
}
```
-`GenericWebApplicationContext` 并未实现 `ConfigurableWebApplicationContext` 的核心方法,也就不能通过文件加载配置,该类设计的目的不是在`web.xml`中进行声明式的安装,而是编程式的安装,例如使用`WebApplicationInitializers`来构建内嵌的上下文;一般很少用到
+`GenericWebApplicationContext` 并未实现 `ConfigurableWebApplicationContext` 的核心方法,也就不能通过文件加载配置,
+该类设计的目的不是在`web.xml`中进行声明式的安装,而是编程式的安装,例如使用`WebApplicationInitializers`来构建内嵌的上下文;一般很少用到
-## 6. StaticWebApplicationContext
+## 5. StaticWebApplicationContext
-因为 [StaticApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/support/StaticApplicationContext.java) 实现功能比较少,放在这里一起解析
+因为 [StaticApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/support/StaticApplicationContext.java)
+实现功能比较少,放在这里一起解析
```java
public class StaticApplicationContext extends GenericApplicationContext {
@@ -610,7 +630,8 @@ public class StaticApplicationContext extends GenericApplicationContext {
}
```
-[StaticWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/StaticWebApplicationContext.java) 实现功能也比较少
+[StaticWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/StaticWebApplicationContext.java)
+实现功能也比较少
```java
public class StaticWebApplicationContext extends StaticApplicationContext
@@ -633,11 +654,13 @@ public class StaticWebApplicationContext extends StaticApplicationContext
}
```
-`StaticWebApplicationContext` 也并未实现 `ConfigurableWebApplicationContext` 的核心方法,也就不能通过文件加载配置,该类设计的目的主要用于测试,不用于产品环境
+`StaticWebApplicationContext` 也并未实现 `ConfigurableWebApplicationContext` 的核心方法,也就不能通过文件加载配置,
+该类设计的目的主要用于测试,不用于产品环境
-## 7. AbstractRefreshableApplicationContext
+## 6. AbstractRefreshableApplicationContext
-因为 [AbstractRefreshableApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java)
+[AbstractRefreshableApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java)
+的主要功能是创建 bean 工厂,刷新上下文数据
```java
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
@@ -671,9 +694,10 @@ public abstract class AbstractRefreshableApplicationContext extends AbstractAppl
}
```
-## 8. AbstractRefreshableConfigApplicationContext
+## 7. AbstractRefreshableConfigApplicationContext
-因为 [AbstractRefreshableConfigApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/support/AbstractRefreshableConfigApplicationContext.java)
+[AbstractRefreshableConfigApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/support/AbstractRefreshableConfigApplicationContext.java)
+的主要功能是可以通过文件加载配置
```java
public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext
@@ -716,9 +740,10 @@ public abstract class AbstractRefreshableConfigApplicationContext extends Abstra
- `AbstractRefreshableConfigApplicationContext` 实现了 `ConfigurableWebApplicationContext` 的核心方法,也就是可以文件加载配置
- `PropertySourcesPropertyResolver`如何是解析路径的,后面再解析
-## 9. XmlWebApplicationContext
+## 8. XmlWebApplicationContext
-因为 [AbstractRefreshableWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/AbstractRefreshableWebApplicationContext.java) 实现功能比较少,放在这里一起解析
+因为 [AbstractRefreshableWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/AbstractRefreshableWebApplicationContext.java)
+实现功能比较少,放在这里一起解析
```java
public abstract class AbstractRefreshableWebApplicationContext extends AbstractRefreshableConfigApplicationContext
@@ -732,7 +757,8 @@ public abstract class AbstractRefreshableWebApplicationContext extends AbstractR
}
```
-因为 [XmlWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/XmlWebApplicationContext.java) 实现功能比较少,放在这里一起解析
+[XmlWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/XmlWebApplicationContext.java)
+的主要功能是定义了默认的配置文件,创建一个 bean 定义的 xml 解析器,并注册 bean 定义
```java
public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
@@ -789,16 +815,17 @@ SpringMVC 框架的默认加载机制便是使用`XmlWebApplicationContext`作
至于`XmlBeanDefinitionReader`如何是解析 bean 定义的,后面再解析
-## 10. AnnotationConfigWebApplicationContext
+## 9. AnnotationConfigWebApplicationContext
[AnnotationConfigWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java)
+的主要功能是可以通过注解载入配置和 bean 定义
```java
public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWebApplicationContext
implements AnnotationConfigRegistry {}
```
-先来看看 [AnnotationConfigRegistry](<[AnnotationConfigWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigRegistry.java)>)
+先来看看 [AnnotationConfigRegistry](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigRegistry.java)
```java
public interface AnnotationConfigRegistry {
@@ -897,9 +924,10 @@ public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWe
实际上,注册 bean 是由`AnnotatedBeanDefinitionReader`完成,扫描包是由`ClassPathBeanDefinitionScanner`完成,这两个类后面再解析
-## 11. GroovyWebApplicationContext
+## 10. GroovyWebApplicationContext
[GroovyWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/GroovyWebApplicationContext.java)
+的运行机制与 `XmlWebApplicationContext` 差不多,从 `groovy` 文件加载配置与 bean 定义
```java
public class GroovyWebApplicationContext extends AbstractRefreshableWebApplicationContext implements GroovyObject {
@@ -947,16 +975,22 @@ public class GroovyWebApplicationContext extends AbstractRefreshableWebApplicati
}
```
-`GroovyWebApplicationContext` 的运行机制与 `XmlWebApplicationContext` 差不多,从 `groovy` 文件加载配置与 bean 定义
+## 11. 综述
-## 12. 综述
+[WebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/WebApplicationContext.java)
+定义了 Web 应用初始化的基本流程,主要有 5 个实现类,常用的是:基于 Xml 加载的`XmlWebApplicationContext`
+与基于注解加载的`AnnotationConfigWebApplicationContext`
-[WebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/WebApplicationContext.java) 定义了 Web 应用初始化的基本流程,主要有 5 个实现类,常用的是:基于 Xml 加载的`XmlWebApplicationContext`与基于注解加载的`AnnotationConfigWebApplicationContext`
+- [GenericWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/GenericWebApplicationContext.java)、[StaticWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/StaticWebApplicationContext.java)
+ :这两者都只是`WebApplicationContext`的基础实现,都不能通过配置文件和注解加载应用配置与 bean
+- [XmlWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/XmlWebApplicationContext.java)
+ :基于 XML 加载应用配置与 bean 的上下文环境,是 SpringMVC 的默认 Context
+- [AnnotationConfigWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java)
+ :基于注解如 `@Configuration, @bean` 等加载应用配置与 bean 的上下文环境,是 SpringBoot 的基础
+- [GroovyWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/GroovyWebApplicationContext.java)
+ :与`XmlWebApplicationContext`的实现差不多,但可以用 Groovy 代替 xml 做配置文件,但目前 Groovy 远不及 Xml 普及,用的仍然不多
-- [GenericWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/GenericWebApplicationContext.java)、[StaticWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/StaticWebApplicationContext.java):这两者都只是`WebApplicationContext`的基础实现,都不能通过配置文件和注解加载应用配置与 bean
-- [XmlWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/XmlWebApplicationContext.java):基于 XML 加载应用配置与 bean 的上下文环境,是 SpringMVC 的默认 Context
-- [AnnotationConfigWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java):基于注解如 `@Configuration, @bean` 等加载应用配置与 bean 的上下文环境,是 SpringBoot 的基础
-- [GroovyWebApplicationContext](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/context/support/GroovyWebApplicationContext.java):与`XmlWebApplicationContext`的实现差不多,但可以用 Groovy 代替 xml 做配置文件,但目前 Groovy 远不及 Xml 普及,用的仍然不多
+## 12. 未完
这一节仍然有一些点留待下次解析:
diff --git a/spring/3.md b/spring/3.md
new file mode 100644
index 0000000..d83fbbd
--- /dev/null
+++ b/spring/3.md
@@ -0,0 +1,1836 @@
+# Spring 源码解析三:SpringMVC 的 Bean 注册、解析、实例化机制
+
+上一篇分析了上下文组件(WebApplicationContext),但留下一些点待分析:
+
+- `ConfigurableListableBeanFactory`如何加载、实例化 bean
+- `ResourceEditorRegistrar`如何注册属性编辑器、属性编辑器如何解析为对象
+- `PathMatchingResourcePatternResolver`如何解析、加载 locationPattern 指定的资源
+- `PropertySourcesPropertyResolver`如何是解析路径的
+- `XmlBeanDefinitionReader`如何是解析 bean 定义的
+- `AnnotatedBeanDefinitionReader`是如何注册 bean 的
+- `ClassPathBeanDefinitionScanner`是如何扫描包的
+
+Bean 的注册、解析、实例化主要是 [ConfigurableListableBeanFactory](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-beans/src/main/java/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.java) 完成的,但`ConfigurableListableBeanFactory`只是一个接口,[DefaultListableBeanFactory](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java) 是其默认实现
+
+先来看看 `DefaultListableBeanFactory` 的集成关系
+
+```
+- SimpleAliasRegistry
+ - DefaultSingletonBeanRegistry
+ - FactoryBeanRegistrySupport
+ - AbstractBeanFactory
+ - AbstractAutowireCapableBeanFactory
+ - DefaultListableBeanFactory
+```
+
+## 1. SimpleAliasRegistry
+
+[SimpleAliasRegistry](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-core/src/main/java/org/springframework/core/SimpleAliasRegistry.java)
+简单的 bean 别名管理器
+
+```java
+public class SimpleAliasRegistry implements AliasRegistry {}
+```
+
+先来看看接口[AliasRegistry](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-core/src/main/java/org/springframework/core/AliasRegistry.java)
+
+```java
+public interface AliasRegistry {
+ // 注册bean别名
+ void registerAlias(String name, String alias);
+
+ // 移除bean别名
+ void removeAlias(String alias);
+
+ // 检查是否是bean别名
+ boolean isAlias(String name);
+
+ // 获取bean别名
+ String[] getAliases(String name);
+}
+```
+
+[SimpleAliasRegistry](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-core/src/main/java/org/springframework/core/SimpleAliasRegistry.java)
+是 `AliasRegistry` 的简单实现
+
+```java
+public class SimpleAliasRegistry implements AliasRegistry {
+ // 别名容器,使用ConcurrentHashMap实现
+ private final Map aliasMap = new ConcurrentHashMap<>(16);
+
+ @Override
+ public void registerAlias(String name, String alias) {
+ synchronized (this.aliasMap) {
+ if (alias.equals(name)) {
+ // 如果名字与别名相同,则删除别名
+ this.aliasMap.remove(alias);
+ }
+ else {
+ // 载入别名
+ this.aliasMap.put(alias, name);
+ }
+ }
+ }
+
+ @Override
+ public void removeAlias(String alias) {
+ synchronized (this.aliasMap) {
+ String name = this.aliasMap.remove(alias);
+ }
+ }
+
+ @Override
+ public boolean isAlias(String name) {
+ return this.aliasMap.containsKey(name);
+ }
+
+ @Override
+ public String[] getAliases(String name) {
+ List result = new ArrayList<>();
+ synchronized (this.aliasMap) {
+ // 根据名字反向找别名
+ retrieveAliases(name, result);
+ }
+ return StringUtils.toStringArray(result);
+ }
+}
+```
+
+## 2. DefaultSingletonBeanRegistry
+
+[DefaultSingletonBeanRegistry](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java)
+默认的单例管理器
+
+```java
+public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {}
+```
+
+先来看看接口[SingletonBeanRegistry](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-beans/src/main/java/org/springframework/beans/factory/config/SingletonBeanRegistry.java)
+
+```java
+public interface SingletonBeanRegistry {
+ // 注册单例bean
+ void registerSingleton(String beanName, Object singletonObject);
+
+ // 获取单例bean
+ Object getSingleton(String beanName);
+}
+```
+
+[DefaultSingletonBeanRegistry](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java)
+是 `SingletonBeanRegistry` 的默认实现
+
+```java
+public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
+ // 单例对象Map: bean name => bean instance
+ private final Map singletonObjects = new ConcurrentHashMap<>(256);
+
+ // 单例生成工厂Map: bean name => ObjectFactory
+ private final Map> singletonFactories = new HashMap<>(16);
+
+ // 单例对象Map: bean name => bean instance(解决循环依赖)
+ private final Map earlySingletonObjects = new ConcurrentHashMap<>(16);
+
+ // 已注册单例对象bean name集合
+ private final Set registeredSingletons = new LinkedHashSet<>(256);
+
+ // 可销毁单例对象Map: bean name => bean instance
+ private final Map disposableBeans = new LinkedHashMap<>();
+
+ // 单例对象拥有内部单例集合Map: bean name => bean instance set(比如class是一个bean,class内部的方法也是一个bean)
+ private final Map> containedBeanMap = new ConcurrentHashMap<>(16);
+
+ // 单例对象的被依赖集合Map: bean name => bean instance set(其他bean依赖这个bean)
+ private final Map> dependentBeanMap = new ConcurrentHashMap<>(64);
+
+ // 单例对象的依赖集合Map: bean name => bean instance set
+ private final Map> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
+}
+```
+
+```java
+public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
+ // 注入单例对象,如果已存在,则报错
+ @Override
+ public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
+ synchronized (this.singletonObjects) {
+ Object oldObject = this.singletonObjects.get(beanName);
+ if (oldObject != null) {
+ throw new IllegalStateException("Could not register object [" + singletonObject +
+ "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
+ }
+ addSingleton(beanName, singletonObject);
+ }
+ }
+
+ protected void addSingleton(String beanName, Object singletonObject) {
+ synchronized (this.singletonObjects) {
+ // 注入,临时和定义都去掉
+ this.singletonObjects.put(beanName, singletonObject);
+ this.singletonFactories.remove(beanName);
+ this.earlySingletonObjects.remove(beanName);
+ this.registeredSingletons.add(beanName);
+ }
+ }
+}
+```
+
+```java
+public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
+ // 获取单例
+ public Object getSingleton(String beanName) {
+ return getSingleton(beanName, true);
+ }
+
+ protected Object getSingleton(String beanName, boolean allowEarlyReference) {
+ // 先尝试从singletonObjects中获取
+ Object singletonObject = this.singletonObjects.get(beanName);
+ // 如果没有,单例已经在创建中,还没有完成
+ if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
+ // 从早期集合中找(可能依赖没有完成)
+ singletonObject = this.earlySingletonObjects.get(beanName);
+ if (singletonObject == null && allowEarlyReference) {
+ // 如果仍然没有,锁住singletonObjects对象,从singletonFactories中创建
+ synchronized (this.singletonObjects) {
+ singletonObject = this.singletonObjects.get(beanName);
+ if (singletonObject == null) {
+ singletonObject = this.earlySingletonObjects.get(beanName);
+ if (singletonObject == null) {
+ ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
+ if (singletonFactory != null) {
+ // 从创建工厂创建单例对象
+ singletonObject = singletonFactory.getObject();
+ this.earlySingletonObjects.put(beanName, singletonObject);
+ this.singletonFactories.remove(beanName);
+ }
+ }
+ }
+ }
+ }
+ }
+ return singletonObject;
+ }
+
+ // 获取单例,如果不存在,就用singletonFactory创建一个新的
+ public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
+ synchronized (this.singletonObjects) {
+ Object singletonObject = this.singletonObjects.get(beanName);
+ if (singletonObject == null) {
+ boolean newSingleton = false;
+ try {
+ // ... 代码省略
+ singletonObject = singletonFactory.getObject();
+ newSingleton = true;
+ }
+ catch (IllegalStateException ex) {
+ // ... 代码省略
+ }
+ catch (BeanCreationException ex) {
+ // ... 代码省略
+ }
+ finally {
+ // ... 代码省略
+ }
+ if (newSingleton) {
+ addSingleton(beanName, singletonObject);
+ }
+ }
+ return singletonObject;
+ }
+ }
+}
+```
+
+## 3. FactoryBeanRegistrySupport
+
+[FactoryBeanRegistrySupport](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryBeanRegistrySupport.java)
+的主要功能是实现对 [FactoryBean](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-beans/src/main/java/org/springframework/beans/factory/FactoryBean.java)
+的支持
+
+先来看看接口 `FactoryBean` 有哪些方法
+
+```java
+public interface FactoryBean {
+ // 获取对象实例
+ T getObject() throws Exception;
+
+ // 获取对象类型
+ Class> getObjectType();
+}
+```
+
+与 [DefaultSingletonBeanRegistry](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java)
+中的对象生成接口 [ObjectFactory](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-beans/src/main/java/org/springframework/beans/factory/ObjectFactory.java)
+不同的是,`FactoryBean` 多了一个 `getObjectType` 用来获取对象类型,这样就可以不用实例化也可以知道 bean 的类型,这对诸如 autowiring 自动装配对象这类功能非常有用
+
+来看看 `FactoryBeanRegistrySupport` 的具体实现
+
+```java
+public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {
+ // FactoryBeans实例缓存: FactoryBean name => object
+ private final Map factoryBeanObjectCache = new ConcurrentHashMap<>(16);
+
+ // 获取factoryBean所代表的bean的类型
+ protected Class> getTypeForFactoryBean(FactoryBean> factoryBean) {
+ try {
+ // 如果有JVM安全检查,绕过
+ if (System.getSecurityManager() != null) {
+ return AccessController.doPrivileged(
+ (PrivilegedAction>) factoryBean::getObjectType, getAccessControlContext());
+ }
+ else {
+ return factoryBean.getObjectType();
+ }
+ }
+ catch (Throwable ex) {
+ // ... 代码省略
+ }
+ }
+
+ // 获取factoryBean所代表的bean的实例
+ protected Object getObjectFromFactoryBean(FactoryBean> factory, String beanName, boolean shouldPostProcess) {
+ // 如果是单例,并且已经创建过
+ if (factory.isSingleton() && containsSingleton(beanName)) {
+ // 锁住父类的singletonObjects
+ synchronized (getSingletonMutex()) {
+ Object object = this.factoryBeanObjectCache.get(beanName);
+ if (object == null) {
+ // 创建实例
+ object = doGetObjectFromFactoryBean(factory, beanName);
+ // 并发处理,有其他线程创建了,就舍弃自己创建的
+ Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
+ if (alreadyThere != null) {
+ object = alreadyThere;
+ }
+ else {
+ if (shouldPostProcess) {
+ // ... 代码省略
+ try {
+ object = postProcessObjectFromFactoryBean(object, beanName);
+ }
+ catch (Throwable ex) {
+ // ... 代码省略
+ }
+ finally {
+ // ... 代码省略
+ }
+ }
+ if (containsSingleton(beanName)) {
+ this.factoryBeanObjectCache.put(beanName, object);
+ }
+ }
+ }
+ return object;
+ }
+ }
+ else {
+ // 如果非单例,或者单例未创建过,直接创建
+ Object object = doGetObjectFromFactoryBean(factory, beanName);
+ if (shouldPostProcess) {
+ try {
+ // 后置处理
+ object = postProcessObjectFromFactoryBean(object, beanName);
+ }
+ catch (Throwable ex) {
+ // ... 代码省略
+ }
+ }
+ return object;
+ }
+ }
+
+ // 创建bean
+ private Object doGetObjectFromFactoryBean(FactoryBean> factory, String beanName) throws BeanCreationException {
+ Object object;
+ try {
+ // 如果有JVM安全检查,绕过
+ if (System.getSecurityManager() != null) {
+ AccessControlContext acc = getAccessControlContext();
+ try {
+ object = AccessController.doPrivileged((PrivilegedExceptionAction