返回介绍

3.3 import 标签的解析

发布于 2025-04-22 22:09:08 字数 4263 浏览 0 评论 0 收藏

对于 Spring 配置文件的编写,我想,经历过庞大项目的人,都有那种恐惧的心理,太多的配置文件了。不过,分模块是大多数人能想到的方法,但是,怎么分模块,那就仁者见仁,智者见智了。使用 import 是个好办法,例如我们可以构造这样的 Spring 配置文件:

applicationContext.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="customerContext.xml" />

  <import resource="systemContext.xml" />

  ... ...

</beans>

applicationContext.xml 文件中使用 import 的方式导入有模块配置文件,以后若有新模块的加入,那就可以简单修改这个文件了。这样大大简化了配置后期维护的复杂度,并使配置模块化,易于管理。我们来看看 Spring 是如何解析 import 配置文件的呢?

protected void importBeanDefinitionResource(Element ele) {

 //获取 resource 属性

  String location = ele.getAttribute(RESOURCE_ATTRIBUTE);

 //如果不存在 resource 属性则不做任何处理

  if (!StringUtils.hasText(location)) {

   getReaderContext().error("Resource location must not be empty", ele);

  return;

 }

  //解析系统属性,格式如: "${user.dir}"

  location = environment.resolveRequiredPlaceholders(location);

  Set<Resource> actualResources = new LinkedHashSet<Resource>(4);

 //判定 location 是决定 URI 还是相对 URI

  boolean absoluteLocation = false;

  try {

   absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI

  (location).isAbsolute();

 }

  catch (URISyntaxException ex) {

   // cannot convert to an URI, considering the location relative

   // unless it is the well-known Spring prefix "classpath*:"

 }

  // Absolute or relative?

 //如果是绝对 URI 则直接根据地址加载对应的配置文件

  if (absoluteLocation) {

   try {

    int importCount = getReaderContext().getReader().loadBeanDefinitions

    (location, actualResources);

    if (logger.isDebugEnabled()) {

     logger.debug("Imported " + importCount + " bean definitions from

     URL location [" + location + "]");

   }

  }

   catch (BeanDefinitionStoreException ex) {

   getReaderContext().error(

    "Failed to import bean definitions from URL location [" +

    location + "]", ele, ex);

  }

 }

  else {

  //如果是相对地址则根据相对地址计算出绝对地址

   try {

    int importCount;

   //Resource 存在多个子实现类,如 VfsResource、FileSystemResource 等,

   //而每个 resource 的 createRelative 方式实现都不一样,所以这里先使用子类的方法

   尝试解析

    Resource relativeResource = getReaderContext(). getResource(). Create

   Relative(location);

    if (relativeResource.exists()) {

     importCount = getReaderContext().getReader(). loadBeanDefinitions

    (relativeResource);

    actualResources.add(relativeResource);

    }else {

    //如果解析不成功,则使用默认的解析器 ResourcePatternResolver 进行解析

     String baseLocation = getReaderContext().getResource().getURL().

    toString();

     importCount = getReaderContext().getReader().loadBeanDefinitions(

     StringUtils.applyRelativePath(baseLocation, location),

    actualResources);

   }

    if (logger.isDebugEnabled()) {

     logger.debug("Imported " + importCount + " bean definitions from

     relative location [" + location + "]");

   }

  }

   catch (IOException ex) {

    getReaderContext().error("Failed to resolve current resource location", ele, ex);

  }

   catch (BeanDefinitionStoreException ex) {

    getReaderContext().error("Failed to import bean definitions from

    relative location [" + location + "]",

    ele, ex);

  }

 }

 //解析后进行监听器激活处理

  Resource[] actResArray = actualResources.toArray(new Resource[actualResources. size()]);

  getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));

}

上面的代码不难,相信配合注释会很好理解,我们总结一下大致流程便于读者更好地梳理,在解析<import 标签时,Spring 进行解析的步骤大致如下。

(1)获取 resource 属性所表示的路径。

(2)解析路径中的系统属性,格式如“${user.dir}”。

(3)判定 location 是绝对路径还是相对路径。

(4)如果是绝对路径则递归调用 bean 的解析过程,进行另一次的解析。

(5)如果是相对路径则计算出绝对路径并进行解析。

(6)通知监听器,解析完成。

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。