簡體   English   中英

如何從配置類實用地設置Spring Active Profiles?

[英]How to set Spring Active Profiles Pragmatically from a configuration class?

在我正在開發的項目中,我們有一些舊的依賴項,它們定義了自己的spring bean,但需要從主應用程序初始化。 這些bean都是使用彈簧配置文件構建的,即生產代碼的“默認”和測試代碼的“測試”。 我們希望不再使用彈簧配置文件,而只需使用@import顯式連接我們的上下文。

我們的想法是封裝所有這些舊的依賴項,以便其他組件不需要關心彈簧配置文件。 因此,從測試的角度來看,應用程序上下文設置可以描述如下:

@ContextConfiguration(classes = {TestContext.class})
@RunWith(SpringJUnit4ClassRunner.class)
public class MyTest { 
  //tests
}

TestContext進一步指向兩個類,其中一個類封裝了舊的依賴項:

@Configuration
@Import(value = {OldComponents.class, NewComponents.class})
public class TestContext {
  //common spring context
}

為了封裝舊組件對配置文件的需求,OldComponents.class如下所示:

@Configuration
@Import(value = {OldContext1.class, OldContext2.class})
public class OldComponents {

  static {
    System.setProperty("spring.profiles.active", "test");
  }

}

這里的問題是靜態塊似乎沒有及時執行。 運行mvn clean install時,測試會收到IllegalStateException,因為無法加載ApplicationContext。 我已經驗證了靜態塊被執行了,但是看起來OldContext1和OldContext2(它們依賴於配置文件)此時已經被加載了,這意味着它已經太晚了。

令人沮喪的是,IntelliJ以這種方式運行測試。 然而,Maven沒有。 有沒有辦法在保持封裝的同時強制使用這些配置文件? 我試過創建一個中間上下文類,但它沒有解決問題。

如果我們在測試類上使用注釋@ActiveProfiles,它運行得很好但是這種方法失敗了。 當然,我們希望在生產中實現相同的目標,這意味着如果我們無法封裝對配置文件的需求,則需要在web.xml中進行配置。

如果您的配置類繼承了AbstractApplicationContext,則可以調用:

getEnvironment().setActiveProfiles("your_profile");

例如:

public class TestContext extends AnnotationConfigWebApplicationContext {

      public TestContext () {
            getEnvironment().setActiveProfiles("test");
            refresh();
      }

}

希望能幫助到你。

這definietly似乎OldContext1OldContext2正在類加載和靜態塊初始化之前OldComponents執行。

雖然我無法解釋為什么你的IDE和Maven之間存在差異(要做到這一點需要深入了解一些,如果不是全部的話):spring 3.x上下文初始化,maven surefire插件,SpringJunit4ClassRunner和內部IntelliJ測試運行器),我可以推薦試試嗎?

@Configuration
@Import(value = {UseTestProfile.class, OldContext1.class, OldContext2.class})
public class OldComponents {
    // moved the System.setProperty call to UseTestProfile.class
}

@Configuration
public class UseTestProfile {
    static {
        System.setProperty("spring.profiles.active", "test");
    }
}

如果我正確理解您的問題,應首先加載類UseTestProfile (您可能想要調查一種方法來保證這一點?)並且導入列表中的其他兩個類應該具有正確初始化所需的系統設置。

希望這可以幫助...

你需要確保,環境首先生效。這就是我的方式:

@Component
public class ScheduledIni {

    @Autowired
    private Environment env;

    @PostConstruct
    public void inilizetion() {
        String mechineName = env.getProperty("MACHINE_NAME");
        if ("test".equals(mechineName) || "production".equals(mechineName) {
            System.setProperty("spring.profiles.default", "Scheduled");
            System.setProperty("spring.profiles.active", "Scheduled");
        }
    }
}

在調度程序中添加注釋ProdileDependsOn以使其工作。

@DependsOn("scheduledIni")
@Profile(value = { "Scheduled" })
@Component

在類中使用@profile注釋來加載如下所示的配置

@Configuration
@Profile("test")
public class UseTestProfile {
}

並在屬性文件中或作為運行時參數設置屬性spring.profiles.active的值

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM