導航:首頁 > 源碼編譯 > 最好的spring源碼

最好的spring源碼

發布時間:2024-01-21 07:57:26

A. 詳解Spring mvc工作原理及源碼分析

Model 模型層 (javaBean組件 = 領域模型(javaBean) + 業務層 + 持久層)

View 視圖層( html、jsp…)

Controller 控制層(委託模型層進行數據處理)

springmvc是一個web層mvc框架,類似struts2。

springmvc是spring的部分,其實就是spring在原有基礎上,又提供了web應用的mvc模塊。

實現機制:

struts2是基於過濾器實現的。

springmvc是基於servlet實現的。

運行速度:

因為過濾器底層是servlet,所以springmvc的運行速度會稍微比structs2快。

struts2是多例的

springmvc單例的

參數封裝:

struts2參數封裝是基於屬性進行封裝。

springmvc是基於方法封裝。顆粒度更細。

⑴ 用戶發送請求至DispatcherServlet。

⑵ DispatcherServlet收到請求調用HandlerMapping查詢具體的Handler。

⑶ HandlerMapping找到具體的處理器(具體配置的是哪個處理器的實現類),生成處理器對象及處理器攔截器(HandlerExcutorChain包含了Handler以及攔截器集合)返回給DispatcherServlet。

⑷ DispatcherServlet接收到HandlerMapping返回的HandlerExcutorChain後,調用HandlerAdapter請求執行具體的Handler(Controller)。

⑸ HandlerAdapter經過適配調用具體的Handler(Controller即後端控制器)。

⑹ Controller執行完成返回ModelAndView(其中包含邏輯視圖和數據)給HandlerAdaptor。

⑺ HandlerAdaptor再將ModelAndView返回給DispatcherServlet。

⑻ DispatcherServlet請求視圖解析器ViewReslover解析ModelAndView。

⑼ ViewReslover解析後返回具體View(物理視圖)到DispatcherServlet。

⑽ DispatcherServlet請求渲染視圖(即將模型數據填充至視圖中) 根據View進行渲染視圖。

⑾ 將渲染後的視圖返回給DispatcherServlet。

⑿ DispatcherServlet將響應結果返回給用戶。

(1)前端控制器DispatcherServlet(配置即可)

功能:中央處理器,接收請求,自己不做任何處理,而是將請求發送給其他組件進行處理。DispatcherServlet 是整個流程的控制中心。

(2)處理器映射器HandlerMapping(配置即可)

功能:根據DispatcherServlet發送的url請求路徑查找Handler

常見的處理器映射器:BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping,

,(不建議使用)

(3)處理器適配器HandlerAdapter(配置即可)

功能:按照特定規則(HandlerAdapter要求的規則)去執行Handler。

通過HandlerAdapter對處理器進行執行,這是適配器模式的應用,通過擴展多個適配器對更多類型的處理器進行執行。

常見的處理器適配器:HttpRequestHandlerAdapter,,

(4)處理器Handler即Controller(程序猿編寫)

功能:編寫Handler時按照HandlerAdapter的要求去做,這樣適配器才可以去正確執行Handler。

(5)視圖解析器ViewReslover(配置即可)

功能:進行視圖解析,根據邏輯視圖名解析成真正的視圖。

ViewResolver負責將處理結果生成View視圖,ViewResolver首先根據邏輯視圖名解析成物理視圖名即具體的頁面地址,再生成View視圖對象,最後對View進行渲染將處理結果通過頁面展示給用戶。

springmvc框架提供了多種View視圖類型,如:jstlView、freemarkerView、pdfView...

(6)視圖View(程序猿編寫)

View是一個介面,實現類支持不同的View類型(jsp、freemarker、pdf...)

引入相關依賴:spring的基本包、springmvc需要的spring-webmvc,日誌相關的slf4j-log4j12,jsp相關的jstl、servlet-api、jsp-api。

因為DispatcherServlet本身就是一個Servlet,所以需要在web.xml配置。

一、使用默認載入springmvc配置文件的方式,必須按照以下規范:

①命名規則:-servlet.xml ====> springmvc-servlet.xml

②路徑規則:-servlet.xml必須放在WEB-INF下邊

二、如果要不按照默認載入位置,則需要在web.xml中通過標簽來指定springmvc配置文件的載入路徑,如上圖所示。

將自定義的 Controller 處理器配置到 spring 容器中交由 spring 容器來管理,因為這里的 springmvc.xml 配置文件中處理器映射器配置的是 BeanNameUrlHandlerMapping ,根據名字可知這個處理器映射器是根據 bean (自定義Controller) 的 name 屬性值url去尋找執行類 Handler(Controller) , 所以bean的name屬性值即是要和用戶發送的請求路徑匹配的 url 。

根據視圖解析路徑:WEB-INF/jsps/index.jsp

功能:根據bean(自定義Controller)的name屬性的url去尋找執行類Controller。

功能:自定義的處理器(Controller)實現了Controller介面時,適配器就會執行Controller的具體方法。

會自動判斷自定義的處理器(Controller)是否實現了Controller介面,如果是,它將會自動調用處理器的handleRequest方法。

Controller介面中有一個方法叫handleRequest,也就是處理器方法。

因此,自定義的Controller要想被調用就必須實現Controller介面,重寫Controller介面中的處理器方法。

B. SpringBoot內置生命周期事件詳解 SpringBoot源碼(十)

SpringBoot中文注釋項目Github地址:扒派族

https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE

本篇接 SpringBoot事件監聽機制源碼分析(上) SpringBoot源碼(九)

溫故而知新,我們來簡單回顧一下上篇的內容,上一篇我們分析了 SpringBoot啟動時廣播生命周期事件的原理羨汪 ,現將關鍵步驟再濃縮總結下:

上篇文章的側重點是分析了SpringBoot啟動時廣播生命周期事件的原理,此篇文章我們再來詳細分析SpringBoot內置的7種生命周期事件的源碼。

分析SpringBoot的生命周期事件,我們先來看一張類結構圖:

由上圖可以看到事件類之間的關系:

EventObject 類是JDK的事件基類,可以說是所有Java事件類的基本,即所有的Java事件類都直接或間接繼承於該類,源碼如下:

可以看到 EventObject 類只有一個屬性 source ,這個屬性是用來記錄最初事件是發生在哪個類,舉個栗子,比如在SpringBoot啟動過程中會發射 ApplicationStartingEvent 事件,而這個事件最初是在 SpringApplication 類中發射的,因此 source 就是 SpringApplication 對象。

ApplicationEvent 繼承了DK的事件基類 EventObject 類,是Spring的事件基類,被所有Spring的具體事件類繼承,源碼如下:

可以看到 ApplicationEvent 有且僅有一個屬性 timestamp ,該屬性是用來記錄事件發生的時間。

SpringApplicationEvent 類繼承了Spring的事件基類 ApplicationEvent ,是所有SpringBoot內置生命周期事件的父類,源碼如下:

可以看到 SpringApplicationEvent 有且僅有一個屬性 args ,該屬性就是SpringBoot啟動時的命令行參數即標注 @SpringBootApplication 啟動類中 main 函數的參數。

接下來我們再來看一下 SpringBoot 內置生命周期事件即 SpringApplicationEvent 的具體子類們。

SpringBoot開始啟動時便會發布 ApplicationStartingEvent 事件,其發布時機在環境變數Environment或容器ApplicationContext創建前但在注冊 ApplicationListener 具體監聽器之後,標志標志 SpringApplication 開始啟動。

可以看到 事件多了一個 environment 屬性,我們不妨想一下,多了 environment 屬性的作用是啥?
答案就是 事件的 environment 屬性作用是利用事件發布訂閱機制,相應監聽器們可以從 事件中取出 environment 變數,然後我們可以為 environment 屬性增加屬性值或讀出 environment 變數中的值。

當SpringApplication已經開始啟動且環境變數 Environment 已經創建後,並且為環境變數 Environment 配置了命令行和 Servlet 等類型的環春弊境變數後,此時會發布 事件。

監聽 事件的第一個監聽器是 ConfigFileApplicationListener ,因為是 ConfigFileApplicationListener 監聽器還要為環境變數 Environment 增加 application.properties 配置文件中的環境變數;此後還有一些也是監聽 事件的其他監聽器監聽到此事件時,此時可以說環境變數 Environment 幾乎已經完全准備好了。

可以看到 事件多了個 類型的 context 屬性, context 屬性的作用同樣是為了相應監聽器可以拿到這個 context 屬性執行一些邏輯,具體作用將在 3.4.4 詳述。

事件在 ApplicationContext 容器創建後,且為 ApplicationContext 容器設置了 environment 變數和執行了 的初始化方法後但在bean定義載入前觸發,標志ApplicationContext已經初始化完畢。

同樣可以看到 ApplicationPreparedEvent 事件多了個 類型的 context 屬性,多了 context 屬性的作用是能讓監聽該事件的監聽器們能拿到 context 屬性,監聽器拿到 context 屬性一般有如下作用:

ApplicationPreparedEvent 事件在 ApplicationContext 容器已經完全准備好時但在容器刷新前觸發,在這個階段 bean 定義已經載入完畢還有 environment 已經准備好可以用了。

ApplicationStartedEvent 事件將在容器刷新後但 ApplicationRunner 和 CommandLineRunner 的 run 方法執行前觸發,標志 Spring 容器已經刷新,此時容器已經准備完畢了。

ApplicationReadyEvent 事件在調用完 ApplicationRunner 和 CommandLineRunner 的 run 方法後觸發,此時標志 SpringApplication 已經正在運行。

可以看到 ApplicationFailedEvent 事件除了多了一個 context 屬性外,還多了一個 Throwable 類型的 exception 屬性用來記錄SpringBoot啟動失敗時的異常。

ApplicationFailedEvent 事件在SpringBoot啟動失敗時觸發,標志SpringBoot啟動失敗。

此篇文章相對簡單,對SpringBoot內置的7種生命周期事件進行了詳細分析。我們還是引用上篇文章的一張圖來回顧一下這些生命周期事件及其用途:

由於有一些小夥伴們建議之前有些源碼分析文章太長,導致耐心不夠,看不下去,因此,之後的源碼分析文章如果太長的話,筆者將會考慮拆分為幾篇文章,這樣就比較短小了,比較容易看完,嘿嘿。

【源碼筆記】Github地址:

https://github.com/yuanmabiji/Java-SourceCode-Blogs

點贊搞起來,嘿嘿嘿!

公眾號【 源碼筆記 】專注於Java後端系列框架的源碼分析。

C. 阿里內部都在用的Spring源碼手冊,學會也是阿里人

最近在使用Spring MVC過程中遇到了一些問題,網上搜索不少帖子後雖然找到了答案和解決方法,但這些答案大部分都只是給了結論,並沒有說明具體原因,感覺總是有點不太滿意。

更重要的是這些所謂的結論大多是抄來抄去,基本源自一家,真實性也有待考證。

那作為程序員怎麼能知其所以然呢?

此處請大家內心默讀三遍。

閱讀源碼的魅力在於:

分享一本阿里內部人都在使用的Spring源碼手冊分享給讀者朋友們,學會掌握了本手冊內容,距離成為阿里人也是成功的跨了一大步子。

第一部分:核心實現原理

第二部分:企業應用

D. Spring事件監聽機制源碼解析

1.Spring事件監聽體系包括三個組件:事件、事件監聽器搜哪,事件廣播器。

事件:定義事件類型和事件源,需要繼承ApplicationEvent。

事件監聽器:用來監聽某一類的事件,並且執行具體業務邏輯,需要實現ApplicationListener 介面或者需要用@ListenerEvent(T)註解。好比觀察者模式中的觀察者。

事件多播器:負責廣播通知所有監聽器,所有的事件監聽判猛器都注冊在了事件多播器中。好比觀察者模式中的被觀察者。Spring容器默認生成的是同步事件多播器。可以自定義事件多播器,定義為非同步方式。

創建 的過程中,會執行refresh()中的()方法。該方法先獲取bean工廠,然後判斷工廠是否包含了beanName 為 applicationEventMulticaster的bean。如果包含了,則獲取該bean,賦值給applicationEventMulticaster 屬性。如果沒有,則創建一個 對象,並且賦值給 applicationEventMulticaster 。實現了源碼如下:

監聽器的注冊有兩種,通過實現 ApplicationListener介面或者添加@EventListener註解。

注冊的邏輯實現在refresh()中的registerListeners()方法裡面。第一步,先獲取當前ApplicationContext中已經添加的 applicationListeners(SpringMVC源碼中有用到),遍歷添加到多播器中。第二步,獲取實現了ApplicationListener介面的listenerBeanNames集合,添加至多掘漏橋播器中。第三步,判斷是否有早期事件,如果有則發起廣播。

思考一下,上面的代碼中第二步為啥添加的是listenerBeanName?

如果監聽器是懶載入的話(即有@Lazy 註解)。那麼在這個時候創建監聽器顯然是不對的,這個時候不能創建監聽器。所以添加監聽器到多播器的具體邏輯放在初始化具體的監聽器之後。通過 BeanPostProcessor 的介面實現。具體的實現類是 ApplicationListenerDetector 。這個類是在 refreah()中prepareBeanFactory()方法中添加的。代碼如下:

在創建 的構造方法中,會執行org.springframework.context.annotation.AnnotationConfigUtils#(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object) 方法。這個方法中會添加兩個 beanDefs, 代碼如下:

EventListenerMethodProcessor:事件監聽器的BeanFactory後置處理器,在前期會創建 DefaultEventListenerFactory ,後期在創建好Bean之後,根據 EventListener 屬性,調用DefaultEventListenerFactory創建具體的 。

DefaultEventListenerFactory:監聽器的創建工廠,用來創建 。

EventListenerMethodProcessor 的類繼承圖如下:

在refreash的()中會調用 org.springframework.context.event.EventListenerMethodProcessor#postProcessBeanFactory方法,獲取EventListenerFactory 類型的 Bean。代碼如下:

在 org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons 方法中,創建完所有的單例Bean 之後,會遍歷所有Bean是否實現了 SmartInitializingSingleton 介面。如果實現介面會執行該 Bean 的 afterSingletonsInstantiated() 方法。代碼如下:

org.springframework.context.event.EventListenerMethodProcessor#afterSingletonsInstantiated 中會調用私有方法 processBean()進行 ApplicationEventAdatper 的創建。代碼如下:

可以通過調用 org.springframework.context.support.AbstractApplicationContext#publishEvent(java.lang.Object, org.springframework.core.ResolvableType) 方法進行事件的調用。代碼如下:

中的 multicasEvent,invokeListener,doInvokeListener 三個方法代碼如下:

SpringMVC中就是通過Spring的事件機制進行九大組件的初始化。

監聽器定義在FrameworkServlet類中,作為內部類。代碼如下:

監聽器的添加在org.springframework.web.servlet.FrameworkServlet# 中進行。通過SourceFilteringListener進行包裝。添加代碼如下:

在refresh中的registerListeners方法進行添加,代碼如下:

在refresh中的finishRefresh()方法中,會調用publishEvnet(new ContextRefreshedEvent(this))發布事件。進行多播器廣播,代碼如下

最終會調到FrameworkServlet.this.onApplicationEvent(event)。

E. Spring源碼解析哪本書好

解析的步驟: 1、載入web.xml、載入監聽器<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 2、ContextLoaderListener 初始化initWebApplicationContext方法創建 org.springframework.web.context.support. XmlWebApplicationContext對象 3、XmlWebApplicationContext調用loadBeanDefinitions方法,該方法主要做兩件事情:初始化XmlBeanDefinitionReader、獲取applicationContext.xml配置文件的路徑、然後把事情交給XmlBeanDefinitionReader來處理 4、XmlBeanDefinitionReader獲取到applicationContext.xml配置文件的路徑、讀取配置文件的內容得到一個輸入流、對輸入流轉碼操作、然後封裝成一個inputSource對象、再然後封裝成一個document對象;在生成document對象的同事也生成了一個Resource對象、這兩個對象分部是:document對象承載配置文件的主要內容信息、Resource承載配置文件的描述信息以及一些驗證信息。 再由Resource對象創建一個XmlReaderContext。完成了以上操作XmlBeanDefinitionReader就把document對象和XmlReaderContext對象交給來處理 5、1)、對XmlReaderContext裝飾成一個BeanDefinitionParserDelegate對象; 2)、迭代document對象、把document對象拆分成Element元素逐個逐個解析; 3)、使用BeanDefinitionParserDelegate裝飾對象解析Element元素或者說標簽。 if (absoluteLocation) { try { int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources); if (logger.isDebugEnabled()) { logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]"); } } catch (BeanDefinitionStoreException ex) { getReaderContext().error( "Failed to import bean definitions from URL location [" + location + "]", ele, ex); } } else { // No URL -> considering resource location as relative to the current file. try { int importCount; Resource relativeResource = getReaderContext().getResource().createRelative(location); if (relativeResource.exists()) { importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource); actualResources.add(relativeResource); } else { String baseLocation = getReaderContext().getResource().getURL().toString(); importCount = getReaderContext().getReader().loadBeanDefinitions( StringUtils.applyRelativePath(baseLocation, location), actualResources); } if (logger.isDebugEnabled()) { logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]"); } } catch (IOException ex) { getReaderContext().error("Failed to resolve current resource location", ele, ex); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]", ele, ex); } } Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]); getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele)); } 解析alias標簽的方法:

F. Spring源碼解析(一)- 容器的基本實現

       Spring使用 基本的JavaBean 來完成以前只可能由EJB完成的事情,是個分層架構。Spring創建bean都需要通過 讀取 、 解析 、 校驗配置文件, 然後注冊創建成Bean。 Spring是一個Bean容器 , 主要作用是替我們管理bean對象 (簡單的Java類對象的生命周期)。不管框架如何強大,還是需要我們程序員來告訴其一些必要信息的(比如要 管理的bean對象的類相關信息、是否開啟組件掃檔納描 等),這些我們稱之為對 Spring框架的配置 ,目前主流的配置方式是 通過使用配置文件或註解。

        Spring中最核心的兩個源雀類: DefaultListableBeanFactory、XmlBeanDifinitionReader。DefaultListableBeanFactory 是整個bean載入的核心部分,是Spring注冊及載入bean的默認實現 。XmlBeanDefinitionReader 主要使用reader屬性對資源文件進行讀取和注冊。

        XML配置文件讀取是Spring中重要的功能,大部分Spring大部分功能都是 以配置作為切入點 。 XmlBeanFactory 繼承自 DefaultListableBeanFactory ,而對於 DefaultListableBeanFactory 不同的地方其實是在 XmlBeanFactory 中使用了自定義的XML讀取器 XmlBeanDefinitionReader ,主要用於從XML文檔中讀取 BeanDefinition, 實現了個性化的 BeanDefinitionReader 讀取, DefaultListableBeanFactory 繼承了 並實現了 以及 BeanDefinitionRegistry 介面。

        Spring的配置文件讀取是通過ClasaPathResource進行封裝的 ,如:new ClassPathResource("bean.xml")。在java中, 將不同來源的資源的讀取邏輯抽象成URL ,通過注冊不同的 handler來處理。 一般handler的類型使用不同的前綴,URL沒有默認定義相對的path路徑,也 沒有提供相關方法對資源進行檢查 ,顧Spring對其內部需要使用到的資源做了屬於自己的抽象結構, 用Resource介面來封裝底層資源。

        Resource 介面繼承 InputStreamSource(封裝了任何能返回InputStream的類)。

        Resource介面抽象了所有Spring內部使用到的底層資源 ,首先它定義了3個能判斷當前資源狀態的方法: 存在性(exists)、可讀性(isReadable)、是否處於打開狀態(isOpen) 。有了Resource介面便可以對所有資源進行統一處理。 ClassPathResource 中的實現是通過class或 classLoader 提供的底層方法進行調用。以此完成對配置文件資源的封裝。

        當通過Resource相關類完成了對配置文件進行封裝,接下來由 XmlBeanDefinitionReader 完成對配置文件的讀取工作。雹蠢早

       XML文件的驗證模式有兩種:DTD、XSD(XML Schema).

        DTD即文檔類型定義, 是一種XML約束模式語言,是XML文件的驗證機制 。是一種保證XML文檔格式正確的有效方法, 可以通過比較XML文檔和DTD文件來查看文檔是否符合規范,元素和標簽的使用是否正確 。一個DTD文檔包含:元素的定義規則、元素間關系的定義規則、元素可使用的屬性、可使用的實體或符號規則。 要使用DTD驗證模式需要在XML文件的頭部聲明。

        XML Schema語言就是XSD。   XML Schema描述了XML文檔的結構。可以用一個指定的XML Schema來驗證某個XML文檔,以檢查該XML文檔是否符合其要求。也可以 通過XML Schema指定一個XML文檔所允許的結構和內容 。XML Schema本身也是一個XML文檔,符合XML語法結構,可以用通用的XML解析器解析它。    

        使用XML Schema文檔對XML實例進行校驗,要聲明名稱空間和指定該名稱空間所對應的XML Schema文檔存儲位置 。通過schemaLocation屬性來指定名稱空間所對應的XML Schema文檔的存儲地址(1、名稱空間URL;2、該名稱空間所標識的XML Schema文件地址或URL地址)。

      另外驗證模式通過 XmlBeanDefinitionReader 中的setValidationMode方法進行設定。而 Spring 用來檢測驗證模式的方法實際上就是判斷是否包含 DOCTYPE ,如果包含就是 DTD ,否則就是 XSD 。

        XML文件經過驗證模式,交由DocumentLoader進行解析成對應的 Document。 而解析的過程中存在這么一環節:(EntityResolver) 根據聲明去尋找對應的DTD定義,以便對文檔進行驗證認證 。也可以通過setEntityResolver設置DTD定義。EntityResolver它用來接收兩個參數publicId和systemId,xsd格式文件通常publicId為null。而對於不同的驗證模式採用不同的解析器進行解析,並把文件轉換成Document文件,用於提取及注冊bean。

          Document 文件通過 BeanDefinitionDocumentReader 進行內部邏輯處理,並提取root用於作為參數繼續完成BeanDefinition的注冊。

閱讀全文

與最好的spring源碼相關的資料

熱點內容
小米桌面文件夾亂碼怎麼回事 瀏覽:854
點歌台app怎麼連接 瀏覽:316
大學電腦編程學什麼好 瀏覽:348
上哪裡取消應用加密 瀏覽:170
電氣控制與可編程式控制制器pdf 瀏覽:85
cad圖紙不能跨文件夾粘貼 瀏覽:254
學生雲伺服器主機 瀏覽:885
單片機狀態周期 瀏覽:620
lua中的android 瀏覽:443
加密貴還是植發貴 瀏覽:662
陽光壓縮機繼電器 瀏覽:971
修改阿里雲伺服器密碼 瀏覽:815
lk4102加密晶元 瀏覽:588
怎麼更改app店面 瀏覽:489
設備部門如何做好伺服器 瀏覽:849
androido下載 瀏覽:478
神奇高量戰法副圖源碼 瀏覽:830
匯編語言設計凱撒密碼加密器 瀏覽:392
主次梁加密是加在哪裡 瀏覽:664
模板匹配演算法matlab 瀏覽:825