String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;
相信大家spring的操作都能够熟练的运用了,对于spring的一些内部实现原理是怎么样的呢?spring的IOC是怎么整合
到web容器中的呢。
在启动时spring会加载ContextLoader.properties文件:
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebAppl
icationContext
从中可以看出XmlWebApplicationContext是web应用加载的类,spring的继承还是比较复杂的,后面再详细讲解
默认的加载的配置文件
public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
/** Default prefix for building a config location for a namespace */
public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
/** 默认文件的后缀名*/
public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
//这个方法是加载配置文件,如果没有设置namespace则加载/WEB-INF/applicationContext.xml,想spring mvc则会设
置namespace,所以
//配置的时候需要用/WEB-INF/xxx.xml,这个以后再讲
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};
}
}
//这边是加载bean配置的地方,稍后详解
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
//第一个被加载的配置文件
String[] configLocations = getConfigLocations();
if (configLocations != null) {
for (String configLocation : configLocations) {
reader.loadBeanDefinitions(configLocation);
}
}
}
那这些配置文件时符合加载的呢,下面让我们一起看看spring的资源
Resource接口抽象了spring内部使用到的资源,它判断了当前资源的存在性、可读性、是否处于打开状态,到classpathResource相信大家在实际编程过程中也使用过他加载过资源文件。ResourceLoader中
String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;
表示该接口加载classpath:下资源,扩展的接口ResourcePatternResolver则能够加载classpath:*下资源,从继承关系可以看出XmlWebApplicationContext本身就是能够进行资源加载。那么下面看下是如何加载资源的。
public int loadBeanDefinitions(String location, Set<Resource> 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;
}
}
从上述可以看出开始的时候会执行最后的else读取单个文件中的内容,即applicationContext.xml中的内容,而if中的则只能在开始读取到文件中的classpath:*才能够读取,先根据路径获取到资源,在根据资源则加载配置文件中的bean