今天要说的是委派模式。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。