2013-10-22 75 views
2

在我的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个春天配置文件:测试生产由我的上下文(加载不同的属性占位每个配置文件)使用。因此,在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装载到“测试”配置文件,如预期所要的文件被加载(测试道具换-一个)。 b.xml是由a.xml导入的,但现在我遇到了一个奇怪的经历,我从b.xml加载的属性文件中的属性值不会被注入。

例如,如果我在我的属性文件中有这样的特性:

connection-ip=1.2.3.4 

,并在我的课我:

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

connectionIP的价值将是“$ {连接-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驻留在src /测试/资源项目B.为什么我得到这个?

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

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

UPDATE

我删除从路径星号(*),以我的属性文件(test-props-for-b.properties)和调试代码的春天。在课堂上使用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下的文件。

回答

0

您是否试图定义弹簧配置文件而不是@ActiveProfiles(profiles =“test”)?

一个例子是在Maven的万无一失插件以这种方式来定义它:

 <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> 
+0

我从eclipse运行我的测试作为junit测试,所以我认为这样做应该没有任何影响,无论如何都会尝试。顺便说一句,如果我在测试过程中检查,我可以看到活动配置文件是“测试”,所以这不是问题。 – forhas

1

调查这个问题后,我的结论:

如果我可以使用适当的文件可以很容易地加载类加载器,这意味着为了从项目A加载文件,来自项目A的类的任何类加载器都可以做到这一点,对于项目B来说也是如此。但是,当使用spring的属性占位符时,类加载器使用ClassPathResource.java,当它试图从不同的项目加载资源时,它不能这样做(一个ClassPathResource获取initiali每个属性占位符,因此每个项目在我的情况)。

我真的不知道如何解决它,目前我已经通过复制我的测试性质的文件(添加的文件中实现一个丑陋的解决方法test-props-for-b.properties为src /测试/资源文件夹项目A,通过这种方式,我将它复制到项目B和A的src/test/resource中)。

我仍在寻找更干净的方式。

+1

从几个月起拉我的头发同样的问题!没有找到干净的解决方案:(属性文件获取复制每个从属模块正在让事情变得一团糟。 – Gopi

+0

嗯,我不是唯一一个,一些安慰:) – forhas