第一种:
使用一个数组,将所有要加载的配置文件放入到数组当中
Java代码
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"a.xml","b.xml"});
第二种:
使用通配符,这种方法不知道对于不在同一个路径下的配置起不起作用,本人没试验过!
Java代码
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/*.xml");
spring的源码是如何实现同时加载两个以上的配置文件的?
我的意思是源码在何处判断是否有两个路径,以及怎么去加载。
最好能贴上源代码。困惑了很久,请高手解决,不胜感激。
1、你疑惑的是classpath 加载方式
2、那就分析ClassPathXmlApplicationContext
*/
[url] public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}[/url]
调用了setConfigLocations(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;
}
}
resolvePath用于替换${} 占位符
这样就能解析出configLocations
3、接下来加载bean
[quote] protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}[/quote]
[quote] public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int counter = 0;
for (String location : locations) {
counter += loadBeanDefinitions(location);
}
return counter;
}
[/quote]
到了重点
[quote]public int loadBeanDefinitions(String location, Set actualResources) throws BeanDefinitionStoreException {
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
int loadCount = loadBeanDefinitions(resources);
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}[/quote]
3.1、重点
3.1.1、getResourceLoader() --->
在AbstractXmlApplicationContext(ClasspathXmlApplicationContext(继承它) beanDefinitionReader.setResourceLoader(this); 即ClasspathXmlApplicationContext本身 通过观察你会发现是DefaultResourceLoader
它的解释:根据不同的前缀返回不同的Resource (到此其实就把你的疑问差不多解决了)
Will return a {@link UrlResource} if the location value is a URL,
3.1.2、模式字符串的加载
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
如果是模式 能找到多个--继续找下去 //classpath:aa*
for (Resource resource : resources) {
actualResources.add(resource);
}
其实你现在再去看下ClasspathResource就可以了
具体使用可以参考
[url]http://jinnianshilongnian.iteye.com/blog/1416322[/url]