From e23735766ca62827f334f9f3957bd6d9c29d4050 Mon Sep 17 00:00:00 2001 From: senntyou Date: Sat, 9 Oct 2021 17:15:25 +0800 Subject: [PATCH] add spring/1 --- README.md | 4 + spring/1.md | 268 ++++++++++++++++++++++------------------------------ 2 files changed, 115 insertions(+), 157 deletions(-) diff --git a/README.md b/README.md index 61e6019..1393abe 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +## Spring 源码解析 + +1. [\[2021-10-09\] SpringMVC 的加载机制](spring/1.md) + ## 前端进阶 1. [\[2018-06-15\] 前后端分离、web 与 static 服务器分离](web-advance/1.md) diff --git a/spring/1.md b/spring/1.md index 355701e..872ba03 100644 --- a/spring/1.md +++ b/spring/1.md @@ -9,7 +9,7 @@ - `spring-jcl`:`spring` 框架的通用日志处理 - `spring-core`:`spring` 框架的核心机制模块,包括 Java 字节码的操作处理与动态生成、依赖注入机制(也叫控制反转)、工具类库、 注解操作、编码处理与数据转换、资源加载与处理、环境加载机制等 -- `spring-beans`:`spring bean` 的定义、加载、解析、编辑 +- `spring-beans`:`spring bean` 的定义、加载、解析、编辑等 - `spring-context`:`spring` 框架的上下文环境,包括应用缓存、应用事件、应用配置、核心注解定义与处理、资源加载、异步与定时任务、数据验证与格式化等 - `spring-aop`:面向切面编程的封装与处理 - `spring-aspects`:使用 [AspectJ](https://www.eclipse.org/aspectj/) 作为底层实现的面向切面编程 @@ -20,7 +20,7 @@ - `spring-oxm`:对 O/X Mapper 的封装 - `spring-messaging`:对 `http, rsocket, simp` 等消息传递协议的封装 - `spring-jms`:对 JMS(Java 消息服务) 的封装 -- `spring-expression`:[Spring Expression Language (SpEL)](https://docs.spring.io/spring-integration/docs/5.3.0.RELEASE/reference/html/spel.html) Spring 表达式语言 +- `spring-expression`:[Spring Expression Language (SpEL)](https://docs.spring.io/spring-integration/docs/5.3.0.RELEASE/reference/html/spel.html) Spring 表达式语言的实现 - `spring-r2dbc`:对 [R2DBC](https://r2dbc.io/) 的封装 - `spring-orm`:对 [JPA](https://www.oracle.com/technical-resources/articles/java/jpa.html) 和 [hibernate](https://hibernate.org/) 的封装 - `spring-web`:提供了 Web 框架的基础结构与技术,如 Http 的调用、过滤、处理等 @@ -28,7 +28,7 @@ - `spring-websocket`:对 WebSocket 的支持 - `spring-webflux`:Reactive Web 框架的实现,与 `spring-webmvc` 相对 -Spring 框架的核心模块主要是:`spring-core`、`spring-beans`、`spring-context`、`spring-web`、`spring-webmvc`,后面也主要从这几个模块来分析。 +SpringMVC 框架的核心模块主要是:`spring-core`、`spring-beans`、`spring-context`、`spring-web`、`spring-webmvc`,后面也主要从这几个模块来分析。 ### 1.1. `spring-core` @@ -38,7 +38,7 @@ Spring 框架的核心模块主要是:`spring-core`、`spring-beans`、`spring 1. `spring-core` 提供了依赖注入机制,这是 `spring bean` 加载的基础,也是我们可以使用 `@Autowired` 自动装载对象等功能的底层机制 1. `spring-core` 提供了环境加载的机制,所以我们可以使用 `application-dev.yml, application-test.yml, application-prod.yml, ...` 来根据环境加载不同的配置 -1. `spring-core` 提供了一个类似 Java SPI 的的扩展机制,可以自动加载其他包指定的类,`spring-boot, spring-cloud` 都依赖这个机制自动加载资源。 +1. `spring-core` 提供了一个类似 Java SPI 的的扩展机制,可以自动实例化其他包指定的类,`spring-boot, spring-cloud` 都依赖这个机制自动加载资源。 在 `META-INF/spring.factories` 文件中定义需要自动加载的类,详细介绍可以参考 [Spring Factories](https://www.jianshu.com/p/00e49c607fa1) ### 1.2. `spring-beans` @@ -46,8 +46,8 @@ Spring 框架的核心模块主要是:`spring-core`、`spring-beans`、`spring Spring bean 的加载与扩展机制有几点需要在这里简单介绍一下: 1. Spring bean 的定义主要是两种:基于注解的定义、基于 XML 文件的定义 -1. `spring-beans` 提供了基于 XML 配置的第三方对 bean 的自定义扩展机制,主要是在 `META-INF/spring.handlers, META-INF/spring.schemas` 文件中定义需要扩展的标签,比如 `, ` -1. 基于注解的自定义扩展,需要依赖 `spring-boot` 的扩展机制 +1. `spring-beans` 提供了基于 XML 配置的、第三方对 bean 的自定义扩展机制,主要是在 `META-INF/spring.handlers, META-INF/spring.schemas` 文件中定义需要扩展的标签,比如 `, ` +1. 基于注解的自定义扩展,需要依赖 `spring-boot` 的扩展加载机制 ### 1.3. `spring-context` @@ -163,7 +163,7 @@ Spring bean 的加载与扩展机制有几点需要在这里简单介绍一下 ```java public interface Servlet { - // 初始化 Servlet,只第一次初始化 + // 初始化 Servlet,只执行一次 public void init(ServletConfig config) throws ServletException; // 响应请求,每次http请求都会调用这个方法 @@ -222,8 +222,6 @@ public abstract class HttpServlet extends GenericServlet { private static final String METHOD_PUT = "PUT"; private static final String METHOD_TRACE = "TRACE"; - public HttpServlet() {} - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { @@ -240,7 +238,7 @@ public abstract class HttpServlet extends GenericServlet { throws ServletException, IOException { NoBodyResponse response = new NoBodyResponse(resp); - + // 调用 doGet,但body设为空body doGet(req, response); response.setContentLength(); } @@ -248,37 +246,19 @@ public abstract class HttpServlet extends GenericServlet { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - String protocol = req.getProtocol(); - String msg = lStrings.getString("http.method_post_not_supported"); - if (protocol.endsWith("1.1")) { - resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg); - } else { - resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg); - } + // ... 代码省略 } protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - String protocol = req.getProtocol(); - String msg = lStrings.getString("http.method_put_not_supported"); - if (protocol.endsWith("1.1")) { - resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg); - } else { - resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg); - } + // ... 代码省略 } protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - String protocol = req.getProtocol(); - String msg = lStrings.getString("http.method_delete_not_supported"); - if (protocol.endsWith("1.1")) { - resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg); - } else { - resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg); - } + // ... 代码省略 } protected void doOptions(HttpServletRequest req, HttpServletResponse resp) @@ -300,50 +280,24 @@ public abstract class HttpServlet extends GenericServlet { String method = req.getMethod(); if (method.equals(METHOD_GET)) { - long lastModified = getLastModified(req); - if (lastModified == -1) { - // servlet doesn't support if-modified-since, no reason - // to go through further expensive logic - doGet(req, resp); - } else { - long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); - if (ifModifiedSince < lastModified) { - // If the servlet mod time is later, call doGet() - // Round down to the nearest second for a proper compare - // A ifModifiedSince of -1 will always be less - maybeSetLastModified(resp, lastModified); - doGet(req, resp); - } else { - resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); - } - } - + // ... 代码省略 + doGet(req, resp); + // ... 代码省略 } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); - } else if (method.equals(METHOD_POST)) { doPost(req, resp); - } else if (method.equals(METHOD_PUT)) { doPut(req, resp); - } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); - } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); - } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); - } else { - // - // Note that this means NO servlet supports whatever - // method was requested, anywhere on this server. - // - String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[1]; errArgs[0] = method; @@ -387,36 +341,36 @@ public abstract class HttpServlet extends GenericServlet { public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware { // 初始化 @Override - public final void init() throws ServletException { - // Set bean properties from init parameters. - PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); - if (!pvs.isEmpty()) { - try { - BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); - ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); - bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); - initBeanWrapper(bw); - bw.setPropertyValues(pvs, true); - } - catch (BeansException ex) { - if (logger.isErrorEnabled()) { - logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); - } - throw ex; - } - } - - // Let subclasses do whatever initialization they like. - initServletBean(); - } + public final void init() throws ServletException { + // Set bean properties from init parameters. + PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); + if (!pvs.isEmpty()) { + try { + BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); + ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); + bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); + initBeanWrapper(bw); + bw.setPropertyValues(pvs, true); + } + catch (BeansException ex) { + if (logger.isErrorEnabled()) { + logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); + } + throw ex; + } + } + + // Let subclasses do whatever initialization they like. + initServletBean(); + } // 初始化由Servlet Config定义的Java Bean,由子类实现,默认不实现 - protected void initBeanWrapper(BeanWrapper bw) throws BeansException { - } + protected void initBeanWrapper(BeanWrapper bw) throws BeansException { + } // 初始化Servlet bean,由子类实现 - protected void initServletBean() throws ServletException { - } + protected void initServletBean() throws ServletException { + } } ``` @@ -798,36 +752,36 @@ public class DispatcherServlet extends FrameworkServlet { ```java public class DispatcherServlet extends FrameworkServlet { private void initHandlerMappings(ApplicationContext context) { - this.handlerMappings = null; + this.handlerMappings = null; // 默认是探测所有的HandlerMapping,包括父上下文 - if (this.detectAllHandlerMappings) { - Map matchingBeans = - BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); - if (!matchingBeans.isEmpty()) { - this.handlerMappings = new ArrayList<>(matchingBeans.values()); - AnnotationAwareOrderComparator.sort(this.handlerMappings); - } - } - else { + if (this.detectAllHandlerMappings) { + Map matchingBeans = + BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); + if (!matchingBeans.isEmpty()) { + this.handlerMappings = new ArrayList<>(matchingBeans.values()); + AnnotationAwareOrderComparator.sort(this.handlerMappings); + } + } + else { // 否则直接获取bean - try { - HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class); - this.handlerMappings = Collections.singletonList(hm); - } - catch (NoSuchBeanDefinitionException ex) {} - } + try { + HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class); + this.handlerMappings = Collections.singletonList(hm); + } + catch (NoSuchBeanDefinitionException ex) {} + } // 如果以上两种都没有定义,则获取默认的处理策略 - if (this.handlerMappings == null) { - this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); - } + if (this.handlerMappings == null) { + this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); + } - // ... 代码省略 - } + // ... 代码省略 + } // 获取默认的处理策略 - protected List getDefaultStrategies(ApplicationContext context, Class strategyInterface) { + protected List getDefaultStrategies(ApplicationContext context, Class strategyInterface) { // 尝试从DispatcherServlet.properties文件中加载 if (defaultStrategies == null) { try { @@ -885,18 +839,18 @@ org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ - org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\ - org.springframework.web.servlet.function.support.RouterFunctionMapping + org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\ + org.springframework.web.servlet.function.support.RouterFunctionMapping org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ - org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ - org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\ - org.springframework.web.servlet.function.support.HandlerFunctionAdapter + org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ + org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\ + org.springframework.web.servlet.function.support.HandlerFunctionAdapter org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\ - org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ - org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver + org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ + org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator @@ -1196,7 +1150,7 @@ public class DispatcherServlet extends FrameworkServlet { } ``` -#### 3.6.3. 后面再解析的几个点 +#### 3.6.3. 需要后面再解析的几个点 `DispatcherServlet` 这个类的解析基本上就差不多了,但还有几点没有解析: @@ -1220,19 +1174,19 @@ public class DispatcherServlet extends FrameworkServlet { ```java public class ContextLoaderListener extends ContextLoader implements ServletContextListener { - @Override - public void contextInitialized(ServletContextEvent event) { + @Override + public void contextInitialized(ServletContextEvent event) { // ContextLoader.initWebApplicationContext - initWebApplicationContext(event.getServletContext()); - } + initWebApplicationContext(event.getServletContext()); + } - @Override - public void contextDestroyed(ServletContextEvent event) { + @Override + public void contextDestroyed(ServletContextEvent event) { // ContextLoader.closeWebApplicationContext - closeWebApplicationContext(event.getServletContext()); + closeWebApplicationContext(event.getServletContext()); // 销毁上下文中以"org.springframework."开头的可销毁bean - ContextCleanupListener.cleanupAttributes(event.getServletContext()); - } + ContextCleanupListener.cleanupAttributes(event.getServletContext()); + } } ``` @@ -1241,15 +1195,15 @@ public class ContextLoaderListener extends ContextLoader implements ServletConte ```java public class ContextLoader { static { - try { + try { // 从ContextLoader.properties文件中加载默认的策略 - ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class); - defaultStrategies = PropertiesLoaderUtils.loadProperties(resource); - } - catch (IOException ex) { - throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage()); - } - } + ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class); + defaultStrategies = PropertiesLoaderUtils.loadProperties(resource); + } + catch (IOException ex) { + throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage()); + } + } } ``` @@ -1274,39 +1228,39 @@ org.springframework.web.context.WebApplicationContext=org.springframework.web.co ```java public class ContextLoader { public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { - // ... 代码省略 + // ... 代码省略 - try { + try { // 如果没有上下文对象,则创建一个新的上下文 // 并调用 configureAndRefreshWebApplicationContext(cwac) 配置并刷新新的上下文 // 默认使用 XmlWebApplicationContext(基于XML加载)作为应用上下文 - if (this.context == null) { - this.context = createWebApplicationContext(servletContext); - } - if (this.context instanceof ConfigurableWebApplicationContext) { - ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context; - // 未激活 - if (!cwac.isActive()) { - if (cwac.getParent() == null) { - ApplicationContext parent = loadParentContext(servletContext); - cwac.setParent(parent); - } + if (this.context == null) { + this.context = createWebApplicationContext(servletContext); + } + if (this.context instanceof ConfigurableWebApplicationContext) { + ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context; + // 未激活 + if (!cwac.isActive()) { + if (cwac.getParent() == null) { + ApplicationContext parent = loadParentContext(servletContext); + cwac.setParent(parent); + } // 配置并刷新应用上下文 - configureAndRefreshWebApplicationContext(cwac, servletContext); - } - } + configureAndRefreshWebApplicationContext(cwac, servletContext); + } + } // 把上下文注册到ServletContext中 - servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); + servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); - // ... 代码省略 + // ... 代码省略 - return this.context; - } - catch (RuntimeException | Error ex) { - // ... 代码省略 - } - } + return this.context; + } + catch (RuntimeException | Error ex) { + // ... 代码省略 + } + } } ```