Sping 里面的適配器模式的實現


適配器模式----------設計模式
最近在看SpringMVC源碼,從中看到了比較優秀的設計模式所以來分享下。

1.適配器模式(Adapter):將一個類的接口轉換成客戶希望的另外一個接口,Adapter模式使得原本由於接口不兼容而不能一起工作的那些類可以在一起工作
具體的詳細知識可以參考這篇文章

http://haolloyin.blog.51cto.com/1177454/346128

http://blog.csdn.net/xtu_xiaoxin/article/details/8796499

適用場景:

1、已經存在的類的接口不符合我們的需求;

2、創建一個可以復用的類,使得該類可以與其他不相關的類或不可預見的類(即那些接口可能不一定兼容的類)協同工作;

3、在不對每一個都進行子類化以匹配它們的接口的情況下,使用一些已經存在的子類。

2.SpringMvc中的適配器(HandlerAdapter)
SpringMVC中的適配器到底是解決以上哪個問題的呢?我們來一步一步看看源碼,看看Spring是怎么做的

首先我們找到前端控制器DispatcherServlet可以把它理解為適配器模式中的Client,它的主要作用在於通過處理映射器(HandlerMapper)來找到相應的Handler(即Controlle(寬泛的概念Controller,以及HttpRequestHandler,Servlet,等等)r),並執行Controller中相應的方法並返回ModelAndView,

mappedHandler.getHandler()其實就是通過Spring容器中獲取到的(寬泛的概念Controller,以及HttpRequestHandler,Servlet,等等)Controller

先短暫回顧下流程

1.DispatcherServlet中的doDispatch

 1 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
 2         HttpServletRequest processedRequest = request;
 3         HandlerExecutionChain mappedHandler = null;
 4         boolean multipartRequestParsed = false;
 5  
 6         WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
 7  
 8         try {
 9             ModelAndView mv = null;
10             Exception dispatchException = null;
11  
12             try {
13                 processedRequest = checkMultipart(request);
14                 multipartRequestParsed = (processedRequest != request);
15  
16                 // 此處通過HandlerMapping來映射Controller
17                 mappedHandler = getHandler(processedRequest);
18                 if (mappedHandler == null || mappedHandler.getHandler() == null) {
19                     noHandlerFound(processedRequest, response);
20                     return;
21                 }
22  
23                 // 獲取適配器
24                 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
25  
26                 // Process last-modified header, if supported by the handler.
27                 String method = request.getMethod();
28                 boolean isGet = "GET".equals(method);
29                 if (isGet || "HEAD".equals(method)) {
30                     long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
31                     if (logger.isDebugEnabled()) {
32                         logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
33                     }
34                     if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
35                         return;
36                     }
37                 }
38  
39                 if (!mappedHandler.applyPreHandle(processedRequest, response)) {
40                     return;
41                 }
42  
43                 // 通過適配器調用controller的方法並返回ModelAndView
44                 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
45  
46                 if (asyncManager.isConcurrentHandlingStarted()) {
47                     return;
48                 }
49  
50                 applyDefaultViewName(processedRequest, mv);
51                 mappedHandler.applyPostHandle(processedRequest, response, mv);
52             }
53             catch (Exception ex) {
54                 dispatchException = ex;
55             }
56             catch (Throwable err) {
57                 // As of 4.3, we're processing Errors thrown from handler methods as well,
58                 // making them available for @ExceptionHandler methods and other scenarios.
59                 dispatchException = new NestedServletException("Handler dispatch failed", err);
60             }
61             processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
62         }
63         catch (Exception ex) {
64             triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
65         }
66         catch (Throwable err) {
67             triggerAfterCompletion(processedRequest, response, mappedHandler,
68                     new NestedServletException("Handler processing failed", err));
69         }
70         finally {
71             if (asyncManager.isConcurrentHandlingStarted()) {
72                 // Instead of postHandle and afterCompletion
73                 if (mappedHandler != null) {
74                     mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
75                 }
76             }
77             else {
78                 // Clean up any resources used by a multipart request.
79                 if (multipartRequestParsed) {
80                     cleanupMultipart(processedRequest);
81                 }
82             }
83         }
84     }

 

2.為什么要使用適配器模式呢?
Controller可以理解為Adaptee(被適配者)其中之一

 

 

 可以看到處理器(寬泛的概念Controller,以及HttpRequestHandler,Servlet,等等)的類型不同,有多重實現方式,那么調用方式就不是確定的,如果需要直接調用Controller方法,需要調用的時候就得不斷是使用if else來進行判斷是哪一種子類然后執行。那么如果后面要擴展(寬泛的概念Controller,以及HttpRequestHandler,Servlet,等等)Controller,就得修改原來的代碼,這樣違背了開閉原則(對修改關閉,對擴展開放)。

3.SpringMvc 是如何使用適配器模式來解決以上問題的呢?
Spring創建了一個適配器接口(HandlerAdapter)使得每一種處理器(寬泛的概念Controller,以及HttpRequestHandler,Servlet,等等)有一種對應的適配器實現類,讓適配器代替(寬泛的概念Controller,以及HttpRequestHandler,Servlet,等等)執行相應的方法。這樣在擴展Controller 時,只需要增加一個適配器類就完成了SpringMVC的擴展了

 1 public interface HandlerAdapter {
 2 
 3 
 4 boolean supports(Object handler);
 5 
 6 
 7 ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
 8 
 9 
10 
11 }

 


supports()方法傳入處理器(寬泛的概念Controller,以及HttpRequestHandler,Servlet,等等)判斷是否與當前適配器支持如果支持則從DispatcherServlet中的HandlerAdapter實現類中返回支持的適配器實現類。handler方法就是代理Controller來執行請求的方法並返回結果。
在DispatchServlert中的doDispatch方法中

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

此代碼通過調用DispatchServlert 中getHandlerAdapter傳入Controller(寬泛的概念Controller,以及HttpRequestHandler,Servlet,等等),來獲取對應的HandlerAdapter 的實現子類,從而做到使得每一種Controller有一種對應的適配器實現類

 

 

 

 

返回后就能通過對應的適配實現類代理Controller(寬泛的概念Controller,以及HttpRequestHandler,Servlet,等等)來執行請求的方法

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

其中一個處理器適配器就是我們常說的最熟悉的Controller類適配器

 


---------------------
作者:_PPB
來源:CSDN
原文:https://blog.csdn.net/u010288264/article/details/53835185
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM