今天要說的是委派模式。java
使用起來 和代理模式有點像,在《設計模式之禪》中講到代理模式就是委派模式,對於這個觀點我不敢苟同。看了《Spring5核心原理與30個類手寫實戰》以及網上查閱資料,我總結了如下幾點:ios
下面分析源碼加深一下理解。web
jdk中有一個典型的委託,衆所周知jvm在加載類是用的雙親委託模型,這又是什麼呢?一個類加載器在加載類時,先把這個請求委託給本身的父類加載器去執行,若是父類加載器還存在父類加載器,就繼續向上委託,直到頂層的啓動類加載器。若是父類加載器可以完成類加載,就成功返回,若是父類加載器沒法完成加載,那麼子加載器纔會嘗試本身去加載。從定義中能夠看到雙親加載模型一個類加載器加載類時,首先不是本身加載,而是委託給父加載器。這就和上面打掃衛生的例子很像。父加載器確定有本身的業務邏輯 ,對比下代理模式,正好印證上面的第二條。下面咱們來看看loadClass
方法的源碼,此方法位於ClassLoader
類裏。spring
在此類裏定義了一個雙親,用於下面的加載。編程
// The parent class loader for delegation // Note: VM hardcoded the offset of this field, thus all new fields // must be added *after* it. private final ClassLoader parent;
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; }
一樣在Method
l類裏咱們經常使用代理執行方法invoke()
也存在相似的機制。設計模式
public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { Class<?> caller = Reflection.getCallerClass(); checkAccess(caller, clazz, obj, modifiers); } } MethodAccessor ma = methodAccessor; // read volatile if (ma == null) { ma = acquireMethodAccessor(); } return ma.invoke(obj, args); }
看完代碼,相信童鞋們對委託和代理區別搞清楚了吧。在spring的DispacherServlet
也實現了委託,讓咱們一塊兒來看下吧。微信
學過spring都知道DispacherServlet
是提供web的集中訪問點,分配任務去給處理器執行app
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
DispacherServlet
將任務分配給處理器,主要由jvm
HandlerAdapter
:肯定當前請求的處理程序適配器HandlerExecutionChain
:肯定當前請求的處理程序。cleanupMultipart()
:清理multipart多餘的資源。HandlerMapping
:將請求映射處處理器ViewReslover
: 解析視圖名到具體試圖實現。從以上咱們能夠看出DispatcherServlet主要負責流程的控制。固然我分析的可能有出入,小夥伴們能夠指出來,一塊兒討論。async
好了,委託模式就到這了,童鞋們只有深刻理解委託和代理的異同點,才能在之後的學習生活中更好的使用,至少還能夠在小夥伴面前裝個逼。哈哈哈哈哈哈哈哈哈
看過個人博文都知道,個人文章會有大幅度代碼,有些人可能會質疑我。我我的認爲,學習東西須要思考,思考有個方向,文字解釋只是引導方向,閱讀了相關的代碼,並思考代碼中應用,纔能有本身的體會 ;光靠別人解釋,吃別人咀嚼過東西沒有味道,體會不到真正的意義。僅表明我的觀點,有不一樣意見能夠提出,一塊兒討論。
本文章爲做者讀書筆記及感悟,其中參考了《spring5核心原理與30個類手寫實戰》以及互聯網上的內容。若有錯誤,請評論或者私聊我,歡迎探討技術問題 。即將畢業,在準備找工做,有朋友想給我介紹的,歡迎添加微信:sllbiao。