《深入分析JavaWeb技術內幕》之讀書筆記(篇三)

冉椿林部落格發表於2018-04-17

title: 《深入分析JavaWeb技術內幕》之讀書筆記(篇三)
tags: [Tomcat架構,設計模式,Spring設計與擴充套件點,SpringMVC工作機制,iBatis對映原理]
categories: 程式設計師技能
date: 2018-4-17 12:47:50

Tomcat的系統架構與設計模式

Tomcat總體結構

conf/server.xml配置檔案:

Tomcat的心臟即為Connector和Container元件:

往外層看,一個Container對應多個Connector(如圖有http和ajp等不同的Connetctor,Connector負責對外交流,接收請求,Container處理Connector接受的請求),它們共同組成一個Service,而多個Service就組成一個Server;
往裡層看,Container含有Engine(Servlet引擎),Engine含有Host(虛擬主機),Host含有Context(一個Context對應一個Web應用),Context含有Wrapper(一個Wrapper對應一個Servlet)。

Service類的實現類為StandardService類。由於Service中,Container只有一個,Connector可多個,因此,StandardService提供setContainer()方法用於設定Container(具體實現:去掉老Container與Service的關係,新增新Container與Service的關係,並一一新增Connector與新Containner的關係),以及addConnector()/removeConnector()方法用於新增/刪除Connector(具體實現:在StandardService類中維護的connectors陣列中增減Connector)。

Server類的實現類為StandardServer類。Server中可有多個Service,因此,StandardServer同樣提供addService()/removeService()方法來增減Service,以及findService()來供外部找到相應的Service。

Connector元件

Connector負責接收瀏覽器發過來的TCP連線請求,建立org.apache.coyote.Requestorg.apache.coyote.Response用於交換資料,之後Container會建立一個新的執行緒,並接收到傳來的Request和Response物件,重新建立org.apache.catalina.connector.Requestorg.apache.catalina.connector.Response物件,進行後續處理。

Container元件

Container使用了經典的責任鏈模式,即從Engine到Warpper,層層關聯。Engine作為頂層,不能呼叫setParent()方法再設定父容器,但可以呼叫addChild()方法新增子容器(且子容器只能是host);Wrapper作為最底層容器,也不能呼叫addChild()方法新增子容器,但可以呼叫setParent()方法設定父容器(且父容器只能是context)。

簡單的tomcat可以沒有Engine和Host。

Spring框架的設計理念與設計模式分析

核心元件

  • Spring的核心元件即:Bean、Context、Core;
  • 三者的形象比喻即:Bean是演員,Context是舞臺背景,Core是演出的道具。
  • Bean即是Object的包裝,Context就是要發現每個Bean之間的關係,為他們建立好並維護這個關係,所以Context就是Bean關係的集合,這個關係集合又叫Ioc容器。而Core就是發現、建立、維護關係所需要的一系列工具,把Core元件看成Util更容易理解。

Spring Bean的建立是典型的工廠模式,頂級介面即BeanFactory,有三個子類,分別是:ListableBeanFactory(表明bean是可列表的)、HierarchicalBeanFactory(表明Bean是有繼承關係的,即每個Bean可能有父Bean)、AutowireCapableBeanFactory(定義Bean的自動裝配規則),以上四個介面共同定義了Bean的集合、關係和行為。

Bean的完整定義在配置檔案的<bean/>節點。當Spring成功解析一個Bean節點時,在spring的內部就會轉化為一個BeanDefnition物件,以後所有的操作都是在這個物件上進行的。

Ioc容器如何工作

如何建立BeanFactory

Ioc容器實際上是COntext元件結合其他兩個元件共同構建的一個Bean關係網。構建的入口即是AbstractApplicationContext類的refresh()

更新BeanFactory,首先就是如果BeanFactory已存在就更新,否則就建立,而更新的程式碼是,如果存在就destroyBeans()closeBeanFactory(),然後createBeanFactory(),建立的原始物件即是DefaultListableBeanFactory。並且後面會呼叫loadBeanDefinitions(beanFactory)。前文說到Spring內部Bean被轉化為一個BeanDefnition物件,該方法即是載入、解析Bean的定義。

Ioc的擴充套件點

構建入口refresh()的實現程式碼處,有這樣兩句關鍵程式碼,體現了Spring的擴充套件點:

//初始化和執行BeanFactoryPostProcessor beans
invokeBeanFactoryPostProcessors(beanFactory);
//初始化和執行BeanPostProcessor beans
registerBeanPostProcessors(beanFactory);

第二句程式碼主要是獲取實現BeanFactoryPostProcessor介面的子類,並執行它的postProcessBeanFactory()方法,該方法顧名思義即是呼叫BeanFactory新增加工器,即當BeanFactory建立時被呼叫。這個方法引數需要傳入一個beanFactory(實際是ConfigurableListableBeanFactory,表示可配置的BeanFactory),說明可以對beanFactory做修改。

第四句程式碼,方法顧名思義是註冊Bean新增加工器,即該方法也是獲取實現了BeanPostProcessor介面的子類,並把它們(Bean新增加工器)註冊到BeanFactory物件的beanPostProcessors變數中。BeanPostProcessor介面定義了兩個方法:postProcessBeforeInitialization()postProcessAfterInitialization(),每當bean物件初始化時,進行相關呼叫,執行使用者自定義的操作。

另外一個就是FactoryBean,這是一個工廠Bean,一個可以產生Bean的Bean。如果一個類繼承FactoryBean,使用者可以自己定義產生例項物件的方法,只需實現它的getObject()方法即可。

由上,Spring的Ioc容器的擴充套件點主要有:

  • BeanFactoryPostProcessor:構建BeanFactory時呼叫;
  • BeanPostProcessor:構建Bean時呼叫;
  • InitializingBean、DisposableBean:Bean例項建立和銷燬時呼叫;
  • FactroyBean:可讓你建立自定義的物件,可實現更多的控制。

Spring中AOP的特性詳解

AOP即通過上面的FactoryBean來進行擴充套件來完成這個特性的。代理類繼承了FactoryBean的ProxyFactoryBean。

設計模式解析之代理模式

即給某一個物件建立一個代理物件,由這個代理物件控制對原物件的引用,代理物件可在呼叫原物件時增加一些額外操作。

Spring MVC的工作機制與設計模式

整體介紹

SpringMVC的嵌入關鍵就是通過配置Web.xml的servlet,核心類即DispatcherServlet,它繼承了HttpServlet,在Servlet的init方法呼叫時DispatcherServlet執行SpringMVC的初始化工作。具體初始化:

  • initMultipartResolver:用於檔案上傳服務;
  • initLocalResolver:用於處理應用的國際化;
  • initThemeResolver:用於定義一個主題;
  • initHandlerMappings:用於定義使用者設定的請求對映關係;核心元件
  • initHandelrAdapters:用於根據Handler的型別定義不同的處理規則;核心元件
  • initHandlerExceptionResolvers:當Handler處理出錯時,會通過這個Handler統一處理;
  • initRequestToViewTranslator:將指定的ViewName按照定義的RequestToViewNameTranslator替換成想要的格式(如加上字首、字尾);
  • initViewResolvers:用於將View解析成頁面。核心元件

Control設計

Control=HandlerMapping+HandlerAdapters

HandlerMapping

HandlerMapping負責幫助我們管理URL和對應處理類(Handler)的對映關係,就是將一個或多個URL對映到一個或多個Spring Bean中。

它的初始化工作完成的兩個最重要的工作就是:將URL與Handler的對應關係儲存在handlerMap集合中,並將所有的interceptors物件儲存在adaptedInterceptors陣列中。

HandlerAdapter

HandlerAdapter用於幫助自定義各種Handler。一般的MVC框架會先定義一個特定介面,讓Handler去實現,然後MVC框架通過呼叫介面方法來呼叫Handler。而SpringMVC此處使用了多介面(如有:HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、SimpleServletHandlerAdapter等),不同介面定義不同方法,然後讓Handler去選擇實現這些個介面,讓Handelr的實現更加靈活。

它的初始化工作即是建立一個HandlerAdapter物件,將這個HandlerAdapter物件儲存在DispatcherServlet的handlerAdapters集合中。

整體呼叫邏輯

URL到來時,DispatcherServlet執行`doDispatch()`方法。
方法會匹配`DispatcherServlet的handlerMappings集合中的某個HandlerMapping物件的某個Handler`,匹配成功後返回一個HandlerExecutionChain物件(處理鏈,這個處理鏈包含使用者定義的多個HandlerInterceptor物件)。
通過呼叫該物件的`getHandler()`方法可以得到Handler物件,通過獲得的Handler物件進一步去匹配`支援該Handler的DispatcherServlet的handlerAdapters集合中的HandlerAdapter物件`,並返回handlerAdapter物件。
然後呼叫這個handlerAdapter物件的`handle()`方法(該方法需傳入Handler物件,並將Handler物件強轉為所繼承的父類,如上的Controller、HttpRequestHandler)。
`handle()`方法將呼叫強轉後的handler的`handleRequest()`方法,並返回ModelAndView物件,最後根據ModelAndView進行渲染。

Model設計

在業務邏輯層通常也有Model例項,不過此處所謂的Model,是指標對模版渲染的Model(ModelAndView)。

ModelAndView物件是連線業務邏輯層與View表現層的橋樑,對SpringMVC來說它也是連線Handler與View的橋樑。

Model顧名思義即會持有一個ModelMap物件和一個View物件(或View名稱)。在Handler中,將模板中需要的物件會存在這個ModelMap中,然後傳遞到View對應的ViewResolvers中,不同的ViewResovler對這個ModelMap中的物件有不同的處理方式。

View設計

View=RequestToViewNameTranslator+ViewResolver

RequestToViewNameTranslator用來支援使用者自定義對ViewName的解析,如給請求的ViewName加上字首或字尾,或替換成特定的字元等。

ViewResolver則是根據ViewName建立View物件。

設計模式解析之模板模式

核心即是:大的邏輯已經定義,要做的就是實現一些具體步驟。

SpringMVC的View設計使用了模板模式,View只定義了介面方法,AbstractView類實現了在View中定義的所有方法,並留有一個抽象方法renderMergedOutputModel給子類去實現。而子類AbstractJasperReportsView和AbstractTeamplateView抽象類實現了上述留有的方法,並進一步細化出了renderReport抽象方法和renderMergedTemplateModel方法給子類去進一步實現。

深入分析iBatis框架之系統架構與對映原理

左邊的SqlMapClient介面主要定義了客戶端的操作行為,包括select、insert、update和delete。而郵編主要定義了當前客戶端在當前執行緒中的執行環境。SqlMapSession可以共享使用,也可以自己建立,如果自己建立,需要在結束時自行關閉。

iBatis通過解析SqlMap配置檔案得到所有的Statement執行語句,同時會形成ParameterMap、ResultMap和SQL。當iBatis構建好RequestScope執行環境後,要做的工作就是把傳過來的物件資料結合ParameterMap中的資訊提取出一個引數陣列,這個陣列的順序對應與SQL中引數的順序,然後呼叫preparedStatement.setXXX(i,parameter)提交引數。

iBatis可以自己管理事務,也可以由外部管理。iBatis自己管理是通過共享SqlMapSession物件實現的,多個Statement執行時共享一個SqlMapSession例項,而且執行緒安全。如果外部程式管理就要自行控制SqlMapSession物件的生命週期。

設計模式解析之簡單工廠模式

核心即:通過判斷其條件,來返回不同的物件例項

iBatis中的DataExchangeFactory即使用了簡單工廠模式,它是一個工廠,它可根據傳遞進來的不同class型別返回不同的物件產品,這裡返回的產品都是單例,當然簡單工廠模式也可以每次建立一個新物件返回給呼叫者。

設計模式解析之工廠模式

與簡單工廠模式不同的是,這裡就不再是一個工廠,而是多個工廠,與一個頂層抽象工廠。如果把伺服器單機比作簡單工廠模式的工廠,那麼伺服器叢集+一個負載均衡伺服器就是工廠模式的多個工廠和頂層抽象工廠。

在iBatis中的DataSourceFacotry就是抽象工廠類,對應的JndiDataSourceFactory和DbcpDataSourceFactory就是具體工廠。

相關文章