无法使用相对路径导入 Spring bean 定义文件

Posted

技术标签:

【中文标题】无法使用相对路径导入 Spring bean 定义文件【英文标题】:Unable to import Spring bean definition file using relative path 【发布时间】:2011-12-21 21:06:03 【问题描述】:

我是 Spring 新手,继承了一个 Spring 项目,该项目在 ProjectName/WebContent/WEB-INF/applicationContext.xml 中具有所有 XML 配置。我试图将配置分解为不同的组件,以便在测试时更容易替换 DataSources 和 Hibernate 配置等内容。

这是我的文件结构:

ProjectName
  ->WebContent
      ->WEB-INF
          ->applicationContext.xml
          ->spring-datasource.xml
          ->spring-hibernate-properties.xml
          ->spring-persistence.xml
  ->test
      ->us.mn.k12... (Java pkgs with JUnit tests)
      ->spring-hsqldb-datasource.xml
      ->spring-test-bean-locations.xml
      ->spring-test-hibernate-properties.xml
  ->src
      ->us.mn.k12... (Java pkgs with production code)

在 WEB-INF/applicationContext.xml 中,我导入以下内容:

<import resource="spring-datasource.xml"/> <!-- Production datasource -->
<import resource="spring-hibernate-properties.xml"/> <!-- Production hibernate properties -->
<import resource="spring-persistence.xml"/> <!--  DAO's, hibernate .hbm.xml mapping files -->

应用程序使用上述配置。

我的 JUnit 测试使用 DbUnit 和 HSQLDB 内存数据库运行。所以我的 JUnit 测试引用了 spring-test-bean-locations.xml,它有以下内容:

<import resource="spring-hsqldb-datasource.xml"/> <!-- HSQLDB datasource for test -->
<import resource="../WebContent/WEB-INF/spring-persistence.xml"/>  <!--  Production DAO's, hibernate .hbm.xml mapping files -->
<import resource="spring-test-hibernate-properties.xml"/> <!-- Hibernate properties for test -->

通过这种方式,我可以指定测试数据源和休眠属性,但可以为 DAO 等重用生产映射文件。但是,我在运行 JUnit 测试时遇到错误。这是异常的相关部分:

Caused by: org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from relative location [../WebContent/WEB-INF/spring-persistence.xml]
Offending resource: class path resource [spring-test-bean-locations.xml]; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [../WebContent/WEB-INF/spring-persistence.xml]; nested exception is java.io.FileNotFoundException: class path resource [../WebContent/WEB-INF/spring-persistence.xml] cannot be opened because it does not exist

现在,如果我将 spring-persistence.xml 移动到 /test 中,这样我就不必使用相对路径,并使用 &lt;import resource="spring-persistence.xml"/&gt; 引用它,那么测试运行良好。所以我认为我的 XML 文件的内容还可以,但是我没有正确导入相对路径。

我在导入相对路径时有什么明显的错误吗?也许更大的问题是,这看起来是一种将 applicationContext.xml 分解为组件以使其更易于测试的合理策略吗?

谢谢!

【问题讨论】:

【参考方案1】:

问题是:WEB-INF 中的任何内容在常规​​项目设置中对 ClassLoader 都不可用(并且 spring 默认使用 ClassLoader 来访问资源)。有一些技巧可以解决这个问题(比如使用 file: 前缀引用上下文),但这些大多是丑陋的。

我建议的一个更好的做法是将上下文文件移出 WEB-INF 并进入专用资源目录(如果您有 maven 设置,则为 src/main/resources)。这样一来,webapp ClassLoader 和本地单元测试 ClassLoader 都可以使用它们。

阅读resources chapter 以进一步了解所涉及的机制。

【讨论】:

感谢肖恩的解释。我们使用 Ant,并且只有 src、test 和 WebContent/WEB-INF 作为项目根目录下的 3 个节点。将生产 Spring xml 文件放在 src 目录中,将测试 Spring xml 放在 test 目录中是典型的设置吗?或者是非 Maven 设置中常用的其他位置。谢谢! @buck64 是的,可以。在 maven 中,有一个约定是让类与资源分开,但对于类加载器来说都是一样的。 如果是这样的话,我的罐子(带有豆子)怎么可能放在 /applications/Foo.ear/FooWebApp.war/WEB-INF/lib 中并且一切正常!? @voipp 如果是什么情况?【参考方案2】:

使用

 <import resource="file:**/WebContent/WEB-INF/spring-persistence.xml" />

它适用于春季 3.2.1.RELEASE。旧版本我不确定。

【讨论】:

以上是关于无法使用相对路径导入 Spring bean 定义文件的主要内容,如果未能解决你的问题,请参考以下文章

即使文件在路径中,也无法从 URL 位置 [classpath:spring/spring-persistence-layer.xml] 导入 bean 定义

面试总结

使用相对于配置文件的路径引用 Spring 属性文件

Spring xml配置文件相对路径问题

Spring - 从类路径资源 [Beans.xml]-NoClassDefFoundError 加载 XML bean 定义

spring 类路径资源中的相对路径