【问题标题】:Import spring context with specific profile使用特定配置文件导入弹簧上下文
【发布时间】:2013-10-22 09:14:03
【问题描述】:

在我的 java-spring-maven Web 应用程序中,我使用了多个 spring 上下文(每个项目的单个上下文)。 为了简单起见,假设我有 2 个 spring 上下文:a.xml 和 b.xml,每个都属于一个项目:项目 A 和项目 B,其中 A 依赖于 B。

a.xml 正在像这样导入 b.xml:

<import resource="classpath*:/b.xml" />

所以在加载a.xml时,b.xml也会被加载。

现在,我的系统中有 2 个弹簧配置文件:test 和 production 供我的上下文使用(为每个配置文件加载不同的属性占位符)。

所以在 a.xml 中我得到了:

<!-- Production profile -->
<beans profile="production">
    <context:property-placeholder
        location="classpath:props-for-a.properties"
        ignore-unresolvable="true" ignore-resource-not-found="true" />
</beans>

<!-- Test profile -->
<beans profile="test">
    <context:property-placeholder
        location="classpath*:test-props-for-a.properties"
        ignore-unresolvable="true" />
</beans>

和 b.xml 中的相同约定(只加载不同的属性文件)。 我的属性文件位于 src/main/resources(生产文件)和 src/test/resources(测试文件)下。

现在我的单元测试看起来像这样:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/a.xml" })
@ActiveProfiles(profiles = "test")
public class SomeTestClass {

    @Test
    public void testMethod() {
    //Some Test
    }
}

在这种情况下,a.xml 被加载到“test”配置文件中,并按预期加载所需的文件(test-props-for-a)。 b.xml 是由 a.xml 导入的,但是现在我遇到了一种奇怪的体验,我从 b.xml 加载的属性文件中的属性值没有被注入。

例如,如果我的属性文件中有这个属性:

connection-ip=1.2.3.4

在我的课上我得到了:

@Value("${connection-ip}")
private String connectionIP;

connectionIP 的值将是“${connection-ip}”而不是“1.2.3.4”。

请注意,文件位置以 classpath* 开头,没有 * 我得到一个 FileNotFoundException:

Caused by: org.springframework.beans.factory.BeanInitializationException: Could not load properties; nested exception is java.io.FileNotFoundException: class path resource [test-props-for-b.properties] cannot be opened because it does not exist 

需要明确的是,文件 test-props-for-b.properties 位于项目 B 的 src/test/resources 下。为什么会得到这个?

如果我运行一个直接加载 b.xml(不是通过 a.xml 导入)的测试,它工作得很好,文件 test-props-for-b.properties 中的测试属性会按预期加载。

我做错了吗?这可能是一个错误吗?如果是这样,您能否提出解决方法?

更新

我从属性文件 (test-props-for-b.properties) 的路径中删除了星号 (*) 并调试了 spring 代码。在 ClassPathResource 类中,此方法抛出异常:

public InputStream getInputStream() throws IOException {
    InputStream is;
    if (this.clazz != null) {
        is = this.clazz.getResourceAsStream(this.path);
    }
    else {
        is = this.classLoader.getResourceAsStream(this.path);
    }
    if (is == null) {
        throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
    }
    return is;
}

这里是变量值:

this.clazz 为空。 this.path 包含文件名 test-props-for-b.properties

这个命令返回null:

this.classLoader.getResourceAsStream(this.path);

这是为什么呢?我可以清楚地看到项目B的src/test/resources下的文件。

【问题讨论】:

    标签: spring classpath maven-3 spring-profiles


    【解决方案1】:

    在调查了这个问题之后,这是我的结论:

    如果我可以使用合适的类加载器,则可以轻松加载文件,这意味着为了从项目 A 加载文件,项目 A 中的任何类加载器都可以做到这一点,对于项目 B 也是如此. 但是,当使用 spring 的属性占位符时,使用了 ClassPathResource.java 的类加载器,并且当它尝试从不同的项目加载资源时,它失败了(每个属性占位符初始化 ClassPathResource,因此每项目)。

    我真的不知道如何解决它,目前我通过复制我的测试属性文件(添加文件 test-props-for-b.properties 到 src/test /resources 项目 A 的文件夹,这样我在项目 B 和 A 的 src/test/resource 中也复制了它。

    我仍在寻找更清洁的方法。

    【讨论】:

    • 几个月以来一直在为同样的问题拉头发!还没有找到干净的解决方案 :( 为每个依赖模块复制的属性文件让事情变得一团糟。
    • 好吧,我不是唯一的,一些安慰:)
    【解决方案2】:

    您是否尝试在外部定义弹簧配置文件而不是 @ActiveProfiles(profiles = "test")?

    一个例子是在maven surefire插件中这样定义:

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${surefire.version}</version>
                <configuration>
                    <systemPropertyVariables>
                        <spring.profiles.active>test</spring.profiles.active>
                    </systemPropertyVariables>
                    <!-- THE REST OF CONFIGURATIONS -->
                </configuration>
            </plugin>
    

    【讨论】:

    • 我将我的测试作为 eclipse 的 junit 测试运行,所以我认为这样做应该没有效果,无论如何都会尝试。顺便说一句,如果我在测试期间检查,我可以看到活动配置文件是“测试”,所以这不是问题。
    猜你喜欢
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 2017-05-27
    • 1970-01-01
    • 2013-10-10
    • 2018-11-18
    • 2014-10-14
    • 2012-11-02
    相关资源
    最近更新 更多