1. 程式人生 > >Spring MVC DispatcherServlet contextConfigLocation設定

Spring MVC DispatcherServlet contextConfigLocation設定

web.xml Spring 控制器配置 
其中contextConfigLocation是怎麼 讀取 並設定到 DispatcherServlet 屬性中 
<servlet> 
   <servlet-name>Dispatcher</servlet-name> 
<servlet-class> 
    org.springframework.web.servlet.DispatcherServlet 
</servlet-class> 
<init-param> 
  <param-name>contextConfigLocation
</param-name> 
  <param-value>/WEB-INF/Config.xml</param-value> 
</init-param> 
</servlet> 

============================================================= 
DispatcherServlet 的 父類 HttpServletBean 中 init方法,根據servlet生命週期,servlet例項建立後,容器會呼叫init方法初始化,此方法宣告為final 所以在其子類都不能重寫,所以當DispatcherServlet 例項建立後,容器呼叫初始化init方法就是執行的此方法。 

Java程式碼  收藏程式碼
  1.  public final void init()  
  2.         throws ServletException  
  3.     {  
  4.         if(logger.isDebugEnabled())  
  5.             logger.debug("Initializing servlet '" + getServletName() + "'");  
  6.         try  
  7.         {  
  8. //ServletConfigPropertyValues是HttpServletBean 的內部類,作用是根據config物件獲取servlet中的配置資訊,封裝為PropertyValue物件放到propertyValueList的list中去
      
  9.             org.springframework.beans.PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), requiredProperties);  
  10. //包裝成BeanWrapper 物件  
  11.             BeanWrapper bw = new BeanWrapperImpl(this);  
  12.             org.springframework.core.io.ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());  
  13.             bw.registerCustomEditor(org.springframework.core.io.Resource.classnew ResourceEditor(resourceLoader));  
  14.             initBeanWrapper(bw);  
  15. //將封裝為PropertyValues 物件的配置資訊,設定到bean也就是DispatcherServlet 例項對應的屬性中。  
  16.             bw.setPropertyValues(pvs, true);  
  17.         }  
  18.         catch(BeansException ex)  
  19.         {  
  20.             logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);  
  21.             throw ex;  
  22.         }  
  23.         initServletBean();  
  24.         if(logger.isDebugEnabled())  
  25.             logger.debug("Servlet '" + getServletName() + "' configured successfully");  
  26.     }  




Java程式碼  收藏程式碼
  1. private static class ServletConfigPropertyValues extends MutablePropertyValues  
  2.     {  
  3.         public ServletConfigPropertyValues(ServletConfig config, Set requiredProperties)  
  4.             throws ServletException  
  5.         {  
  6.             Set missingProps = requiredProperties == null || requiredProperties.isEmpty() ? null : ((Set) (new HashSet(requiredProperties)));  
  7. //獲取DispatcherServlet 在web.xml中的配置的所有<init-param>的名字  
  8.             Enumeration en = config.getInitParameterNames();  
  9.             do  
  10.             {  
  11.                 if(!en.hasMoreElements())  
  12.                     break;  
  13.                 String property = (String)en.nextElement();  
  14. //獲取對應名字的值  
  15.                 Object value = config.getInitParameter(property);  
  16.                 addPropertyValue(new PropertyValue(property, value));  
  17.                 if(missingProps != null)  
  18.                     missingProps.remove(property);  
  19.             } while(true);  
  20.             if(missingProps != null && missingProps.size() > 0)  
  21.                 throw new ServletException("Initialization from ServletConfig for servlet '" + config.getServletName() + "' failed; the following required properties were missing: " + StringUtils.collectionToDelimitedString(missingProps, ", "));  
  22.             else  
  23.                 return;  
  24.         }  
  25.     }  


====================================================================== 
如果忽略contextConfigLocation此設定,則預設為“/WEB-INF/<servlet name>-servlet.xml”,其中<servlet name>以Servlet 名替換 

HttpServletBean 中 init方法中: 
initServletBean()方法有子類FrameworkServlet重寫 
在FrameworkServlet的initServletBean()方法中, 
this.webApplicationContext = initWebApplicationContext(); 
完成DispatcherServlet 使用的webApplicationContext 的建立和初始化。 
具體建立由FrameworkServlet的: 
protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) 方法實現, 
在方法最後呼叫wac.refresh();初始化完成資原始檔定位,解析配置檔案生成Document物件,從這個物件中解析各個bean定義生成beanDefinition物件,最後註冊到該WebApplicationContext 容器中 

在AbstractApplicationContext中提供了refresh()方法的實現。。。。。 

在XmlWebApplicationContext中: 
Java程式碼  收藏程式碼
  1. protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {  
  2.     String[] configLocations = getConfigLocations();  
  3.        if (configLocations != null) {  
  4.     for (String configLocation : configLocations) {  
  5.             reader.loadBeanDefinitions(configLocation);  
  6.             }  
  7.         }  
  8.     }  


getConfigLocations()獲取配置檔案的位置,實際呼叫了父類AbstractRefreshableConfigApplicationContext 
中的: 

Java程式碼  收藏程式碼
  1. protected String[] getConfigLocations() {  
  2. return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());  
  3.     }  


如果configLocations 已經有值就返回,沒有呼叫getDefaultConfigLocations()方法獲取預設的位置; 

而getDefaultConfigLocations()方法由子類XmlWebApplicationContext重寫: 


Java程式碼  收藏程式碼
  1. protected String[] getDefaultConfigLocations() {  
  2.    if (getNamespace() != null) {  
  3.  return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};  
  4.         }  
  5.     else {  
  6. return new String[] {DEFAULT_CONFIG_LOCATION};  
  7.         }  
  8.     }  

DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace()+DEFAULT_CONFIG_LOCATION_SUFFIX = 
/WEB-INF/<servlet name>-servlet.xml