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

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

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

     执行的代码片段:
...
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
...


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


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


if(mappedHandler.getHandler() instanceof MultiActionController){
   ((MultiActionController)mappedHandler.getHandler()).xxx
}else if(mappedHandler.getHandler() instanceof XXX){
    ...
}else if(...){
   ...
}
...


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

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


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


//定义一个Adapter接口
public interface HandlerAdapter {
	public boolean supports(Object handler);
	public void handle(Object handler);
}

//以下是三种Controller实现
public interface Controller {

}

public class HttpController implements Controller{
	public void doHttpHandler(){
		System.out.println("http...");
	}
}

public class SimpleController implements Controller{
	public void doSimplerHandler(){
		System.out.println("simple...");
	}
}

public class AnnotationController implements Controller{
	public void doAnnotationHandler(){
		System.out.println("annotation...");
	}
}


//下面编写适配器类

public class SimpleHandlerAdapter implements HandlerAdapter {


	public void handle(Object handler) {
		((SimpleController)handler).doSimplerHandler();
	}

	public boolean supports(Object handler) {
		return (handler instanceof SimpleController);
	}

}


public class HttpHandlerAdapter implements HandlerAdapter {

	public void handle(Object handler) {
		((HttpController)handler).doHttpHandler();
	}

	public boolean supports(Object handler) {
		return (handler instanceof HttpController);
	}

}



public class AnnotationHandlerAdapter implements HandlerAdapter {

	public void handle(Object handler) {
		((AnnotationController)handler).doAnnotationHandler();
	}

	public boolean supports(Object handler) {
		
		return (handler instanceof AnnotationController);
	}

}


//模拟一个DispatcherServlet
import java.util.ArrayList;
import java.util.List;


public class DispatchServlet {
	
	public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>(); 
	
	public DispatchServlet(){
		handlerAdapters.add(new AnnotationHandlerAdapter());
		handlerAdapters.add(new HttpHandlerAdapter());
		handlerAdapters.add(new SimpleHandlerAdapter());
	}
	
	
	public void doDispatch(){
		
		//此处模拟SpringMVC从request取handler的对象,仅仅new出,可以出,             
                     //不论实现何种Controller,适配器总能经过适配以后得到想要的结果
//		HttpController controller = new HttpController();
//		AnnotationController controller = new AnnotationController();
		SimpleController controller = new SimpleController();
		//得到对应适配器
		HandlerAdapter adapter = getHandler(controller);
		//通过适配器执行对应的controller对应方法
		adapter.handle(controller);
		
	}
	
	public HandlerAdapter getHandler(Controller controller){
		for(HandlerAdapter adapter: this.handlerAdapters){
			if(adapter.supports(controller)){
				return adapter;
			}
		}
		return null;
	}
	
	public static void main(String[] args){
		new DispatchServlet().doDispatch();
	}
	
}





通过这个模式可以看出 开源代码 中的精妙, 我们在看框架源码时需要有目标的看,这样会找到很多自己需要学习的东西, 目前很多分析源码的帖子大部分是讲解what,how,
以此来抛砖引玉,希望各位能够一起来讨论 “why ”

你可能感兴趣的:(springMVC)