spring源代码解析四Word文档下载推荐.docx
《spring源代码解析四Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《spring源代码解析四Word文档下载推荐.docx(45页珍藏版)》请在冰豆网上搜索。
initHandlerAdapters();
initHandlerExceptionResolvers();
initRequestToViewNameTranslator();
initViewResolvers();
}
//这里是对DispatcherServlet的初始化方法,根据名字我们很方面的看到对各个SpringMVC主要元素的初始化
protectedvoidinitFrameworkServlet()throwsServletException,BeansException{
}
看到注解我们知道,这是DispatcherSerlvet的初始化过程,它是在WebApplicationContext已经存在的情况下进行的,也就意味着在初始化它的时候,IOC容器应该已经工作了,这也是我们在web.xml中配置Spring的时候,需要把DispatcherServlet的load-on-startup的属性配置为2的原因。
对于具体的初始化过程,很容易理解,我们拿initHandlerMappings()来看看:
privatevoidinitHandlerMappings()throwsBeansException{
if(this.detectAllHandlerMappings){
//这里找到所有在上下文中定义的HandlerMapping,同时把他们排序
//因为在同一个上下文中可以有不止一个handlerMapping,所以我们把他们都载入到一个链里进行维护和管理
MapmatchingBeans=BeanFactoryUtils.beansOfTypeIncludingAncestors(
getWebApplicationContext(),HandlerMapping.class,true,false);
if(!
matchingBeans.isEmpty()){
this.handlerMappings=newArrayList(matchingBeans.values());
//这里通过order属性来对handlerMapping来在list中排序
Collections.sort(this.handlerMappings,newOrderComparator());
}
else{
try{
Objecthm=getWebApplicationContext().getBean(HANDLER_MAPPING_BEAN_NAME,HandlerMapping.class);
this.handlerMappings=Collections.singletonList(hm);
catch(NoSuchBeanDefinitionExceptionex){
//Ignore,we'
lladdadefaultHandlerMappinglater.
//如果在上下文中没有定义的话,那么我们使用默认的BeanNameUrlHandlerMapping
if(this.handlerMappings==null){
this.handlerMappings=getDefaultStrategies(HandlerMapping.class);
……..
privatevoidinitHandlerMappings()throwsBeansException{
if(this.detectAllHandlerMappings){
//这里找到所有在上下文中定义的HandlerMapping,同时把他们排序
//因为在同一个上下文中可以有不止一个handlerMapping,所以我们把他们都载入到一个链里进行维护和管理
MapmatchingBeans=BeanFactoryUtils.beansOfTypeIncludingAncestors(
matchingBeans.isEmpty()){
//这里通过order属性来对handlerMapping来在list中排序
else{
try{
catch(NoSuchBeanDefinitionExceptionex){
lladdadefaultHandlerMappinglater.
//如果在上下文中没有定义的话,那么我们使用默认的BeanNameUrlHandlerMapping
if(this.handlerMappings==null){
........
怎样获得上下文环境,可以参见我们前面的对IOC容器在web环境中加载的分析。
DispatcherServlet把定义了的所有HandlerMapping都加载了放在一个List里待以后进行使用,这个链的每一个元素都是一个handlerMapping的配置,而一般每一个handlerMapping可以持有一系列从URL请求到SpringController的映射,比如SimpleUrl
HandlerMaaping中就定义了一个map来持有这一系列的映射关系。
DisptcherServlet通过HandlerMapping使得Web应用程序确定一个执行路径,就像我们在HanderMapping中看到的那样,HandlerMapping只是一个借口:
publicinterfaceHandlerMapping{
publicstaticfinalStringPATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE=
Conventions.getQualifiedAttributeName(HandlerMapping.class,"
pathWithinHandlerMapping"
);
//实际上维护一个HandlerExecutionChain,这是典型的Command的模式的使用,这个执行链里面维护handler和拦截器
HandlerExecutionChaingetHandler(HttpServletRequestrequest)throwsException;
publicinterfaceHandlerMapping{
publicstaticfinalStringPATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE=
//实际上维护一个HandlerExecutionChain,这是典型的Command的模式的使用,这个执行链里面维护handler和拦截器
}
他的具体实现只需要实现一个接口方法,而这个接口方法返回的是一个HandlerExecutionChain,实际上就是一个执行链,就像在Command模式描述的那样,这个类很简单,就是一个持有一个Interceptor链和一个Controller:
publicclassHandlerExecutionChain{
privateObjecthandler;
privateHandlerInterceptor[]interceptors;
publicclassHandlerExecutionChain{
而这些Handler和Interceptor需要我们定义HandlerMapping的时候配置好,比如对具体的SimpleURLHandlerMapping,他要做的就是根据URL映射的方式注册Handler和Interceptor,自己维护一个放映映射的handlerMap,当需要匹配Http请求的时候需要使用这个表里的信息来得到执行链。
这个注册的过程在IOC容器初始化SimpleUrlHandlerMapping的时候就被完成了,这样以后的解析才可以用到map里的映射信息,这里的信息和bean文件的信息是等价的,下面是具体的注册过程:
protectedvoidregisterHandlers(MapurlMap)throwsBeansException{
if(urlMap.isEmpty()){
logger.warn("
Neither'
urlMap'
nor'
mappings'
setonSimpleUrlHandlerMapping"
//这里迭代在SimpleUrlHandlerMapping中定义的所有映射元素
Iteratorit=urlMap.keySet().iterator();
while(it.hasNext()){
//这里取得配置的url
Stringurl=(String)it.next();
//这里根据url在bean定义中取得对应的handler
Objecthandler=urlMap.get(url);
//Prependwithslashifnotalreadypresent.
url.startsWith("
/"
)){
url="
+url;
//这里调用AbstractHandlerMapping中的注册过程
registerHandler(url,handler);
protectedvoidregisterHandlers(MapurlMap)throwsBeansException{
if(urlMap.isEmpty()){
//这里迭代在SimpleUrlHandlerMapping中定义的所有映射元素
while(it.hasNext()){
//这里取得配置的url
//这里根据url在bean定义中取得对应的handler
//Prependwithslashifnotalreadypresent.
)){
//这里调用AbstractHandlerMapping中的注册过程
在AbstractMappingHandler中的注册代码:
protectedvoidregisterHandler(StringurlPath,Objecthandler)throwsBeansException,IllegalStateException{
//试图从handlerMap中取handler,看看是否已经存在同样的Url映射关系
ObjectmappedHandler=this.handlerMap.get(urlPath);
if(mappedHandler!
=null){
//如果是直接用bean名做映射那就直接从容器中取handler
this.lazyInitHandlers&
&
handlerinstanceofString){
StringhandlerName=(String)handler;
if(getApplicationContext().isSingleton(handlerName)){
handler=getApplicationContext().getBean(handlerName);
//或者使用默认的handler.
if(urlPath.equals("
/*"
setDefaultHandler(handler);
//把url和handler的对应关系放到handlerMap中去
this.handlerMap.put(urlPath,handler);
protectedvoidregisterHandler(StringurlPath,Objecthandler)throwsBeansException,IllegalStateException{
//试图从handlerMap中取handler,看看是否已经存在同样的Url映射关系
=null){
//如果是直接用bean名做映射那就直接从容器中取handler
handlerinstanceofString){
if(getApplicationContext().isSingleton(handlerName)){
//或者使用默认的handler.
//把url和handler的对应关系放到handlerMap中去
handlerMap是持有的一个HashMap,里面就保存了具体的映射信息:
privatefinalMaphandlerMap=newHashMap();
privatefinalMaphandlerMap=newHashMap();
而SimpleUrlHandlerMapping对接口HandlerMapping的实现是这样的,这个getHandler根据在初始化的时候就得到的映射表来生成DispatcherServlet需要的执行链
publicfinalHandlerExecutionChaingetHandler(HttpServletRequestrequest)throwsException{
//这里根据request中的参数得到其对应的handler,具体处理在AbstractUrlHandlerMapping中
Objecthandler=getHandlerInternal(request);
//如果找不到对应的,就使用缺省的handler
if(handler==null){
handler=this.defaultHandler;
//如果缺省的也没有,那就没办法了
returnnull;
//如果handler不是一个具体的handler,那我们还要到上下文中取
if(handlerinstanceofString){
//生成一个HandlerExecutionChain,其中放了我们匹配上的handler和定义好的拦截器,就像我们在HandlerExecutionChain中看到的那样,它持有一个handler和一个拦截器组。
returnnewHandlerExecutionChain(handler,this.adaptedInterceptors);
publicfinalHandlerExecutionChaingetHandler(HttpServletRequestrequest)throwsException{
//这里根据request中的参数得到其对应的handler,具体处理在AbstractUrlHandlerMapping中
//如果找不到对应的,就使用缺省的handler
if(handler==null){
//如果缺省的也没有,那就没办法了
//如果handler不是一个具体的handler,那我们还要到上下文中取
if(handlerinstanceofString){
我们看看具体的handler查找过程:
protectedObjectgetHandlerInternal(HttpServletRequestrequest)throwsException{
//这里的HTTPRequest传进来的参数进行分析,得到具体的路径信息。
StringlookupPath=this.urlPathHelper.getLookupPathForRequest(request);
…….//下面是根据请求信息的查找
returnlookupHandler(lookupPath,request);
protectedObjectlookupHandler(StringurlPath,HttpServletRequestrequest){
//如果能够直接能在SimpleUrlHandlerMapping的映射表中找到,那最好。
Objecthandler=