spring-IOC 1
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
?