无法使用相对路径导入 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 中,这样我就不必使用相对路径,并使用 <import resource="spring-persistence.xml"/>
引用它,那么测试运行良好。所以我认为我的 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 - 从类路径资源 [Beans.xml]-NoClassDefFoundError 加载 XML bean 定义