4.2 spring-import 标签的解析;
对于spring配置文件的编写,我想,对于经历过庞大项目的人,都有那种恐惧的心理,太多的配置文件。不过,分模块都是大多数人能想到的方法,但是,怎么分模块,那就是仁者见仁,智者见智了。我的策略是使用import。
基本代码格式如下
web.xml
<?xml version="1.0" encoding="gb2312"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <import resource="CTIContext.xml" /> <import resource="customerContext.xml" /> <import resource="customerServingContext.xml" /> <import resource="manageContext.xml" /> <import resource="routineContext.xml" /> <import resource="systemContext.xml" /> </beans>
applicationContext.xml文件中使用import的方式导入有模块配置文件,以后若有新模块的加入,那就可以简单修改这个文件了,这样大大的简化了配置文件后期的复杂程度;
Spring 的解析代码如下;
1 /** 2 * Parse an "import" element and load the bean definitions from the given resource 3 * into the bean factory. 4 */ 5 protected void importBeanDefinitionResource(Element ele) { 6 // 获取resource 属性 7 String location = ele.getAttribute(RESOURCE_ATTRIBUTE); 8 // 如果不存在resource ,则不做任何处理 9 if (!StringUtils.hasText(location)) { 10 getReaderContext().error("Resource location must not be empty", ele); 11 return; 12 } 13 14 // Resolve system properties: e.g. "${user.dir}" 15 // 解析系统属性.格式如 : ${user.dir} 16 location = environment.resolveRequiredPlaceholders(location); 17 18 Set<Resource> actualResources = new LinkedHashSet<Resource>(4); 19 20 // Discover whether the location is an absolute or relative URI 21 // 判断是绝对地址还是相对地址 22 boolean absoluteLocation = false; 23 try { 24 absoluteLocation = ResourcePatternUtils.isUrl(location) 25 || ResourceUtils.toURI(location).isAbsolute(); 26 } 27 catch (URISyntaxException ex) { 28 // cannot convert to an URI, considering the location relative 29 // unless it is the well-known Spring prefix "classpath*:" 30 } 31 32 // Absolute or relative? 33 // 如果是绝对地址,则直接根据地址加载对应的配置文件 34 if (absoluteLocation) { 35 try { 36 int importCount = getReaderContext().getReader().loadBeanDefinitions( 37 location, actualResources); 38 if (logger.isDebugEnabled()) { 39 logger.debug("Imported " + importCount 40 + " bean definitions from URL location [" + location + "]"); 41 } 42 } 43 catch (BeanDefinitionStoreException ex) { 44 getReaderContext().error( 45 "Failed to import bean definitions from URL location [" 46 + location + "]", ele, ex); 47 } 48 } 49 else { 50 // No URL -> considering resource location as relative to the current file. 51 // 如果是相对地址,则计算出绝对地址 52 try { 53 int importCount; 54 // Resource 的多个子类 ,如 VfsResource,FileSystemResource,ClassPathResource 55 // 而每个Resource的createRelative 方法都不太一样所以这里先使用子类的方法尝试解析, 56 Resource relativeResource = getReaderContext().getResource().createRelative( 57 location); 58 if (relativeResource.exists()) { 59 importCount = getReaderContext().getReader().loadBeanDefinitions( 60 relativeResource); 61 actualResources.add(relativeResource); 62 } 63 else { 64 // 如果解析不成功,则使用默认解析器ResourcePatternResolver 进行解析 65 String baseLocation = getReaderContext().getResource().getURL().toString(); 66 importCount = getReaderContext().getReader().loadBeanDefinitions( 67 StringUtils.applyRelativePath(baseLocation, location), 68 actualResources); 69 } 70 if (logger.isDebugEnabled()) { 71 logger.debug("Imported " + importCount 72 + " bean definitions from relative location [" + location 73 + "]"); 74 } 75 } 76 catch (IOException ex) { 77 getReaderContext().error("Failed to resolve current resource location", 78 ele, ex); 79 } 80 catch (BeanDefinitionStoreException ex) { 81 getReaderContext().error( 82 "Failed to import bean definitions from relative location [" 83 + location + "]", ele, ex); 84 } 85 } 86 // 解析后进行监听器激活处理 87 Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]); 88 getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele)); 89 }