解析SpringMVC源码中使用到的“适配器”模式

前言  
    关于SpringMVC初始化ContextLoader中的XMLWebApplicationContext,以及DispatcherServlet初始化等等,这样的原理 已经有N多的前辈和牛人总结过了, 我就不在这里重复轮子了。~ 
     废话  
    Spring源码还是层次十分分明的,只要了解原理,相信看起来也不会很困难, 但是它的精髓还有其中使用到的设计模式, “架构”少不了模式, Spring正是因为采用大量的模式而使其易于用户扩展。 

     正文  
    找到DispatcherServlet类中的doDispatch体,我们可以看到,它的作用是相当于在Servlet的 doService调用的。 也就是用来传递request给我们编写的Controller并执行相应的方法、返回ModeView对象。 

     执行的代码片段: 
Java代码   收藏代码
  1. ...  
  2. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());  
  3. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());  
  4. ...  


mappedHandler.getHandler()得到的是Controller对象 
而此处并非采用直接 调用.handlerRequest或者MultiActionController中编写的自定义方法,而采用了一个HandlerAdapter 的接口。 


此处采用了适配器模式, 由于Controller的类型不同,有多重实现方式,那么调用方式就不是确定的,如果需要直接调用Controller方法,需要在代码中写成如下形式: 


Java代码   收藏代码
  1. if(mappedHandler.getHandler() instanceof MultiActionController){  
  2.    ((MultiActionController)mappedHandler.getHandler()).xxx  
  3. }else if(mappedHandler.getHandler() instanceof XXX){  
  4.     ...  
  5. }else if(...){  
  6.    ...  
  7. }  
  8. ...  


这样假设如果我们增加一个HardController,就要在代码中加入一行 if(mappedHandler.getHandler() instanceof  HardController) 
这种形式就使得程序难以维护,也违反了设计模式中的开闭原则 --  对扩展开放,对修改关闭。 

因此Spring定义了一个适配接口,使得每一种Controller有一种对应的适配器实现类, 
让适配器代替controller执行相应的方法。这样在扩展Controller 时,只需要增加一个适配器类就完成了SpringMVC的扩展了,真的是很精巧的做法! 


废话不多说还是上代码吧,为了看得清楚,就自己实现一套代码来模拟springMVC, 直接贴Spring源码容易降低关注点。 


Java代码   收藏代码
  1. //定义一个Adapter接口  
  2. public interface HandlerAdapter {  
  3.     public boolean supports(Object handler);  
  4.     public void handle(Object handler);  
  5. }  
  6.   
  7. //以下是三种Controller实现  
  8. public interface Controller {  
  9.   
  10. }  
  11.   
  12. public class HttpController implements Controller{  
  13.     public void doHttpHandler(){  
  14.         System.out.println("http...");  
  15.     }  
  16. }  
  17.   
  18. public class SimpleController implements Controller{  
  19.     public void doSimplerHandler(){  
  20.         System.out.println("simple...");  
  21.     }  
  22. }  
  23.   
  24. public class AnnotationController implements Controller{  
  25.     public void doAnnotationHandler(){  
  26.         System.out.println("annotation...");  
  27.     }  
  28. }  
  29.   
  30.   
  31. //下面编写适配器类  
  32.   
  33. public class SimpleHandlerAdapter implements HandlerAdapter {  
  34.   
  35.   
  36.     public void handle(Object handler) {  
  37.         ((SimpleController)handler).doSimplerHandler();  
  38.     }  
  39.   
  40.     public boolean supports(Object handler) {  
  41.         return (handler instanceof SimpleController);  
  42.     }  
  43.   
  44. }  
  45.   
  46.   
  47. public class HttpHandlerAdapter implements HandlerAdapter {  
  48.   
  49.     public void handle(Object handler) {  
  50.         ((HttpController)handler).doHttpHandler();  
  51.     }  
  52.   
  53.     public boolean supports(Object handler) {  
  54.         return (handler instanceof HttpController);  
  55.     }  
  56.   
  57. }  
  58.   
  59.   
  60.   
  61. public class AnnotationHandlerAdapter implements HandlerAdapter {  
  62.   
  63.     public void handle(Object handler) {  
  64.         ((AnnotationController)handler).doAnnotationHandler();  
  65.     }  
  66.   
  67.     public boolean supports(Object handler) {  
  68.           
  69.         return (handler instanceof AnnotationController);  
  70.     }  
  71.   
  72. }  
  73.   
  74.   
  75. //模拟一个DispatcherServlet  
  76. import java.util.ArrayList;  
  77. import java.util.List;  
  78.   
  79.   
  80. public class DispatchServlet {  
  81.       
  82.     public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();   
  83.       
  84.     public DispatchServlet(){  
  85.         handlerAdapters.add(new AnnotationHandlerAdapter());  
  86.         handlerAdapters.add(new HttpHandlerAdapter());  
  87.         handlerAdapters.add(new SimpleHandlerAdapter());  
  88.     }  
  89.       
  90.       
  91.     public void doDispatch(){  
  92.           
  93.         //此处模拟SpringMVC从request取handler的对象,仅仅new出,可以出,               
  94.                      //不论实现何种Controller,适配器总能经过适配以后得到想要的结果  
  95. //      HttpController controller = new HttpController();  
  96. //      AnnotationController controller = new AnnotationController();  
  97.         SimpleController controller = new SimpleController();  
  98.         //得到对应适配器  
  99.         HandlerAdapter adapter = getHandler(controller);  
  100.         //通过适配器执行对应的controller对应方法  
  101.         adapter.handle(controller);  
  102.           
  103.     }  
  104.       
  105.     public HandlerAdapter getHandler(Controller controller){  
  106.         for(HandlerAdapter adapter: this.handlerAdapters){  
  107.             if(adapter.supports(controller)){  
  108.                 return adapter;  
  109.             }  
  110.         }  
  111.         return null;  
  112.     }  
  113.       
  114.     public static void main(String[] args){  
  115.         new DispatchServlet().doDispatch();  
  116.     }  
  117.       
  118. }  





通过这个模式可以看出 开源代码 中的精妙, 我们在看框架源码时需要有目标的看,这样会找到很多自己需要学习的东西, 目前很多分析源码的帖子大部分是讲解what,how, 
以此来抛砖引玉,希望各位能够一起来讨论 “why ”
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页