2013-10-22 73 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