Spring MVC源碼——Servlet WebApplicationContext

上一篇筆記(Spring MVC源碼——Root WebApplicationContext)中記錄了下 Root WebApplicationContext 的初始化代碼.這一篇來看 Servlet WebApplicationContext 的初始化代碼

DispatcherServlet?是另一個需要在?web.xml?中配置的類, Servlet WebApplicationContext 就由它來創建和初始化.

HttpServletBean

HttpServletBean?簡單繼承了?HttpServlet, 負責將 init-param 中的參數注入到當前?Servlet?實例的屬性中, 并且為子類提供了增加 requiredProperties 的能力.?HttpServletBean?并不依賴于 Spring 容器.

來看一下它的?init()?方法:

public final void init() throws ServletException {// Set bean properties from init parameters.// 從 ServletConfig 中取出初始化參數到 PropertyValues。ServletConfigPropertyValues 的構造器中將會檢查是否缺失了必要屬性PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);if (!pvs.isEmpty()) {try {// 將 servlet 對象包裝成 BeanWrapper ,從而能夠以 Spring 的方式(反射)來注入參數BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());// 注冊 PropertyEditor,遇到 Resource 類型的屬性時,用 ResourceEditor 解析bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));// 初始化 BeanWrapper,空方法
            initBeanWrapper(bw);// 注入屬性,忽略沒有 setter 的屬性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();
}
private static class ServletConfigPropertyValues extends MutablePropertyValues {public ServletConfigPropertyValues(ServletConfig config, Set<String> requiredProperties)throws ServletException {// 將 requiredProperties 拷貝到新的 Set missingPropsSet<String> missingProps = (!CollectionUtils.isEmpty(requiredProperties) ?new HashSet<>(requiredProperties) : null);// 將 ServletConfig 中的初始化參數取出,添加到 MutablePropertyValues 中Enumeration<String> paramNames = config.getInitParameterNames();while (paramNames.hasMoreElements()) {String property = paramNames.nextElement();Object value = config.getInitParameter(property);addPropertyValue(new PropertyValue(property, value));if (missingProps != null) {missingProps.remove(property);}}// Fail if we are still missing properties.if (!CollectionUtils.isEmpty(missingProps)) {// 存在必須出現的條件沒出現throw new ServletException("Initialization from ServletConfig for servlet '" + config.getServletName() +"' failed; the following required properties were missing: " +StringUtils.collectionToDelimitedString(missingProps, ", "));}}
}

FrameworkServlet

FrameworkServlet?是一個更具體的 Servlet 基類. 它有以下兩個功能:

  • 每個 servket 管理一個?WebApplicationContext?實例.
  • 無論請求是否成功, 根據請求處理發布事件.

FrameworkServlet?重寫了?HttpServletBean?的?initServletBean()?方法, 這個方法會在 所有 servlet 的屬性被注入之后執行, 來看一下代碼:

protected final void initServletBean() throws ServletException {getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'");if (logger.isInfoEnabled()) {logger.info("Initializing Servlet '" + getServletName() + "'");}long startTime = System.currentTimeMillis();try {// 初始化 webApplicationContextthis.webApplicationContext = initWebApplicationContext();// 在容器被加載后執行,由子類來實現一些必要的初始化
        initFrameworkServlet();}catch (ServletException | RuntimeException ex) {logger.error("Context initialization failed", ex);throw ex;}// 略去打印日志的部分... 
}

initWebApplicationContext()?方法會初始化并返回一個容器:

protected WebApplicationContext initWebApplicationContext() {// 獲取 Root WebApplicationContextWebApplicationContext rootContext =WebApplicationContextUtils.getWebApplicationContext(getServletContext());WebApplicationContext wac = null;if (this.webApplicationContext != null) {// A context instance was injected at construction time -> use it// 一個上下文已經被注入進來wac = this.webApplicationContext;if (wac instanceof ConfigurableWebApplicationContext) {// 如果是 ConfigurableWebApplicationContext,ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;if (!cwac.isActive()) {// 沒有激活,設置父容器,配置并且刷新容器if (cwac.getParent() == null) {cwac.setParent(rootContext);}configureAndRefreshWebApplicationContext(cwac);}}}if (wac == null) {// 嘗試從 ServletContext 中獲取一個容器wac = findWebApplicationContext();}if (wac == null) {// 創建一個新的容器并初始化wac = createWebApplicationContext(rootContext);}if (!this.refreshEventReceived) {// 沒有觸發過刷新時間synchronized (this.onRefreshMonitor) {// 手動觸發刷新事件
            onRefresh(wac);}}if (this.publishContext) {// Publish the context as a servlet context attribute.// 將容器發布到 ServletContext 的屬性上String attrName = getServletContextAttributeName();getServletContext().setAttribute(attrName, wac);}return wac;
}

onRefresh()?方法供子類來重寫,?DispatcherServlet?重寫了這個方法來初始化 MVC 中的一些組件:

@Override
protected void onRefresh(ApplicationContext context) {initStrategies(context);
}protected void initStrategies(ApplicationContext context) {initMultipartResolver(context);initLocaleResolver(context);initThemeResolver(context);initHandlerMappings(context);initHandlerAdapters(context);initHandlerExceptionResolvers(context);initRequestToViewNameTranslator(context);initViewResolvers(context);initFlashMapManager(context);
}

initWebApplicationContext()?方法調用的其他方法其實和?ContextLoader?中的方法比較類似, 這里就不再放上來了, 有興趣的可以訪問我的源碼注釋.

?總結

通過本篇博客以及上一篇博客,相信大家對springmvc的上下文有了明確的認識。總的來說,默認springmvc項目會有兩個上下文(root webapplicationcontext 和 servlet webapplicationcontext)。接下來的博文會帶大家認識一下springboot項目的上下文以及springmvc項目上下文和springboot項目上下文的異同點,敬請期待。

?

轉自:https://www.cnblogs.com/FJH1994/p/10813687.html

轉載于:https://www.cnblogs.com/hujunzheng/p/10824788.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/531195.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/531195.shtml
英文地址,請注明出處:http://en.pswp.cn/news/531195.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Springboot源碼——應用程序上下文分析

前兩篇(Spring MVC源碼——Root WebApplicationContext 和 Spring MVC源碼——Servlet WebApplicationContext)講述了springmvc項目創建上下文的過程&#xff0c;這一篇帶大家了解一下springboot項目創建上下文的過程。 SpringApplication引導類 SpringApplication類用于啟動或…

基于zookeeper實現分布式配置中心(一)

最近在學習zookeeper&#xff0c;發現zk真的是一個優秀的中間件。在分布式環境下&#xff0c;可以高效解決數據管理問題。在學習的過程中&#xff0c;要深入zk的工作原理&#xff0c;并根據其特性做一些簡單的分布式環境下數據管理工具。本文首先對zk的工作原理和相關概念做一下…

基于zookeeper實現分布式配置中心(二)

上一篇&#xff08;基于zookeeper實現分布式配置中心&#xff08;一&#xff09;&#xff09;講述了zookeeper相關概念和工作原理。接下來根據zookeeper的特性&#xff0c;簡單實現一個分布式配置中心。 配置中心的優勢 1、各環境配置集中管理。 2、配置更改&#xff0c;實時推…

Redis分布式鎖實戰

背景 目前開發過程中&#xff0c;按照公司規范&#xff0c;需要依賴框架中的緩存組件。不得不說&#xff0c;做組件的大牛對CRUD操作的封裝&#xff0c;連接池、緩存路由、緩存安全性的管控都處理的無可挑剔。但是有一個小問題&#xff0c;該組件沒有對分布式鎖做實現&#xff…

基于RobotFramework實現自動化測試

Java robotframework seleniumlibrary 使用Robot Framework Maven Plugin&#xff08;http://robotframework.org/MavenPlugin/&#xff09;執行自動化測試chromedriver下載&#xff1a; http://chromedriver.storage.googleapis.com/index.htmlchromedriver和chrome版本對應…

Springboot國際化信息(i18n)解析

國際化信息理解 國際化信息也稱為本地化信息 。 Java 通過 java.util.Locale 類來表示本地化對象&#xff0c;它通過 “語言類型” 和 “國家/地區” 來創建一個確定的本地化對象 。舉個例子吧&#xff0c;比如在發送一個具體的請求的時候&#xff0c;在header中設置一個鍵值對…

看了就知道為什么別人C語言學習效率那么高了

談及C語言&#xff0c;我想C語言功能強大都應該知道、應用廣泛&#xff0c;一旦掌握了后&#xff0c;你就可以理直氣壯地對他人說“我是電腦高手&#xff01;”&#xff0c;而且以后若是再自學其他語言就顯得輕而易舉了。憂慮的是&#xff0c;C語言般博大精深&#xff0c;太難學…

C語言一看就能上手的干貨!你確定你不來看嗎?

本地環境設置 如果您想要設置 C 語言環境&#xff0c;您需要確保電腦上有以下兩款可用的軟件&#xff0c;文本編輯器和 C 編譯器。 文本編輯器 這將用于輸入您的程序。文本編輯器包括 Windows Notepad、OS Edit command、Brief、Epsilon、EMACS 和 vim/vi。文本編輯器的名稱…

C語言爆炸干貨,小白你還不來看看嘛!

①&#xff1a;數據類型 int(整型)&#xff0c;short int(短整型)&#xff0c;long int(長整型)&#xff0c; char(字符型)&#xff0c;float&#xff08;單精度浮點型&#xff09; double&#xff08;雙精度浮點型&#xff09; C語言編程交流群815393895 ②&#xff1a;邏…

10萬碼農五年的C語言筆記!你現在知道別人為什么這么優秀了嗎?

c語言對許多同學來說確實是一門比較難學的課程&#xff0c;不僅抽象&#xff0c;而且繁瑣&#xff0c;但這又是一門不得不學的課程。前兩節可能還有興致聽一聽&#xff0c;然而&#xff0c;再過幾節課就是一臉蒙比。憑空要想出一道題的算法和程序&#xff0c;根本無從下手。 所…

C語言從來都沒有過時,你大爺終究是你大爺

直到今天&#xff0c;有人在喊C語言過時的語言&#xff0c;還有什么值得學習的&#xff0c;現在看Python&#xff0c;PHP等語言現在都很容易用&#xff0c;誰還在學習老C語言&#xff0c;其實這是真的嗎&#xff1f;作者下載了兩種語言的源代碼作為下載器。由于空間的限制&…

C語言超級瑪麗菜單模塊源碼

C語言是面向過程的&#xff0c;而C&#xff0b;&#xff0b;是面向對象的 C和C的區別&#xff1a; C是一個結構化語言&#xff0c;它的重點在于算法和…

C語言使用函數必須知道的3點注意事項!

C語言是面向過程的&#xff0c;而C&#xff0b;&#xff0b;是面向對象的 C和C的區別&#xff1a; C是一個結構化語言&#xff0c;它的重點在于算法和數據結構。C程序的設計首要考慮的是如何通過一個過程&#xff0c;對輸入&#xff08;或環境條件&#xff09;進行運算處理得…

C語言/C++編程學習:C語言環境設置!

C語言是面向過程的&#xff0c;而C&#xff0b;&#xff0b;是面向對象的 C和C的區別&#xff1a; C是一個結構化語言&#xff0c;它的重點在于算法和數據結構。C程序的設計首要考慮的是如何通過一個過程&#xff0c;對輸入&#xff08;或環境條件&#xff09;進行運算處理得…

C語言指針原來也可以這么的通俗易懂!

C語言是面向過程的&#xff0c;而C&#xff0b;&#xff0b;是面向對象的 C和C的區別&#xff1a; C是一個結構化語言&#xff0c;它的重點在于算法和數據結構。C程序的設計首要考慮的是如何通過一個過程&#xff0c;對輸入&#xff08;或環境條件&#xff09;進行運算處理得…

C語言過時了?你在做夢?

為什么要使用C語言&#xff1f; 在過去的四十年里&#xff0c;C語言已經成為世界上最流行、最重要的一種編程語言。 C是一種融合了控制特性的現代語言&#xff0c;而我們已發現在計算機科學的理論和實踐中&#xff0c;控制特性是很重要的。其設計使得用戶可以自然地采用自頂向…

C/C++的轉義字符詳解

所有的ASCII碼都可以用“\”加數字&#xff08;一般是8進制數字&#xff09;來表示。而C中定義了一些字母前加"\"來表示常見的那些不能顯示的ASCII字符&#xff0c;如\0,\t,\n等&#xff0c;就稱為轉義字符&#xff0c;因為后面的字符&#xff0c;都不是它本來的ASCI…

C語言深入理解!助你向大佬邁進!

Dennis Ritchie 過世了&#xff0c;他發明了C語言&#xff0c;一個影響深遠并徹底改變世界的計算機語言。一門經歷40多年的到今天還長盛不衰的語言&#xff0c;今天很多語言都受到C的影響&#xff0c;C&#xff0c;Java&#xff0c;C#&#xff0c;Perl&#xff0c; PHP&#xf…

【初涉C語言】程序員歡迎來到C語言的世界!

計算機發展史 機器語言所有的代碼里面只有0和1優點&#xff1a;直接對硬件產生作用&#xff0c;程序的執行效率非常高缺點&#xff1a;指令又多又難記、可讀性差、無可移植性匯編語言符號化的機器語言&#xff0c;用一個符號&#xff08;英文單詞、數字&#xff09;來代表一條…

C語言和C++的區別整理詳解!

c和c主要區別 根據書中的描述&#xff0c;進行了整理 推薦一個我自己的C/C交流裙815393895 1、 源代碼文件的擴展名 摘自1.4.1 C實現源代碼文件的擴展名UNIXC、cc、cxx、cGNU CC、cc、cxx、cpp、cDigital Marscpp、cxxBorland CcppWatcomcppMicrosoft Visual Ccpp、cxx、cc…