对于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 }