SpringMVC项目中configLoaction
源头:configLocation通常配置在web.xml中的 init-param 和 context-param 标签中。
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>xxx</param-value>
</init-param>
</servlet>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>xxx</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
使用:init-param 中配置的configLocaion路径会在DispatcherServlet初始化,配置刷新WebApplicationContext时使用到;context-param 中配置的contextConfigLocation路径会在ContextLoaderListener初始化,配置刷新WebApplicationContext时使用到;
1. 设置contextConfigLocation
1.1 ContextLoaderListener:将contextConfigLocation设置到WebApplicationContext
//类ContextLoaderListener 106行 Listener的初始化方法
@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}
//类ContextLoader 294行
//初始化WebapplicationContext,该上下文中通常管理驱动应用后端的中间层和数据层的bean
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
...
configureAndRefreshWebApplicationContext(cwac, servletContext);
...
}
//类ContextLoader 413行
//从web容器上下文中取得配置文件所有位置 设置到WebapplicationContext中
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
...
//从web容器上下文中获取contextConfigLocation的值,即<context-param>标签中<param-name>为contextConfigLocation的值
String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (configLocationParam != null) {
//这里wac 默认是XmlWebApplicationContext
wac.setConfigLocation(configLocationParam);
}
...
}
//类AbstractRefreshableConfigApplicationContext 67行
//可以用【,; \t\n】这些分割符配置多路径
public void setConfigLocation(String location) {
setConfigLocations(StringUtils.tokenizeToStringArray(location, CONFIG_LOCATION_DELIMITERS));
}
//类AbstractRefreshableConfigApplicationContext 75行
//contextConfigLocation的值最终设置到
//AbstractRefreshableConfigApplicationContext的属性中 String[] configLocations;
public void setConfigLocations(String... locations) {
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
1.1 DispatcherServlet:将contextConfigLocation设置到FrameworkServlet
//类HttpServletBean 147行 DispatcherServlet的初始化
@Override
public final void init() throws ServletException {
...
//从ServletConfig中获取配置参数
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
if (!pvs.isEmpty()) {
//将this关联到BeanWrapper
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
initBeanWrapper(bw);
//将pvs中获取的参数设置到this(DispatcherServlet)中
bw.setPropertyValues(pvs, true);
...
}
//类FrameworkServlet 354行
//将contextConfigLocation设置到FrameServlet的属性中
//该方法被反射调用 BeanWrapperImpl$BeanPropertyHandler.setValue(obj,obj);
public void setContextConfigLocation(String contextConfigLocation) {
this.contextConfigLocation = contextConfigLocation;
}
2. BeanFactory中对contextConfigLocation的使用
//类AbstractApplicationContext 515行
//WebApplicationContext上下文刷新方法
@Override
public void refresh() throws BeansException, IllegalStateException {
...
//创建配置BeanFactory并返回
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
...
}
//类AbstractApplicationContext 614行
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//创建并配置BeanFactory
refreshBeanFactory();
...
}
//类AbstractApplicationContext 614行
@Override
protected final void refreshBeanFactory() throws BeansException {
...
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
//加载Bean定义,这里需要读取配置文件
//所以会用到contextConfigLocation
loadBeanDefinitions(beanFactory);
...
}
//类XmlWebApplicationContext 81行
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
...
loadBeanDefinitions(beanDefinitionReader);
}
//类XmlWebApplicationContext 121行
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
//获取配置文件路径
String[] configLocations = getConfigLocations();
...
}
//类AbstractRefreshableWebApplicationContext 137行
@Override
public String[] getConfigLocations() {
return super.getConfigLocations();
}
//类AbstractRefreshableConfigApplicationContext 98行
//这里this.configLocations就是开始时读取web容器上下文中contextConfigLocation
//设置到WebApplicationContext的值
//若开始就没有设置,这里使用默认路径
protected String[] getConfigLocations() {
return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());
}
//类XmlWebApplicationContext 136行
//默认 /WEB-INF/applicationContext.xml 或
// /WEB-INF/ + namespace + .xml
@Override
protected String[] getDefaultConfigLocations() {
if (getNamespace() != null) {
return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};
}
else {
return new String[] {DEFAULT_CONFIG_LOCATION};
}
}