如何从配置类实用地设置Spring Active Profiles?

时间:2013-10-09 11:59:51

标签: java spring maven intellij-idea

在我正在开发的项目中,我们有一些旧的依赖项,它们定义了自己的spring bean,但需要从主应用程序初始化。这些bean都是使用弹簧配置文件构建的,即生产代码的“默认”和测试代码的“测试”。我们希望不再使用弹簧配置文件,而只需使用@import显式连接我们的上下文。

这个想法是封装所有这些旧的依赖项,以便其他组件不需要关心spring配置文件。因此,从测试的角度来看,应用程序上下文设置可以描述如下:

@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中进行配置。

4 个答案:

答案 0 :(得分:0)

如果您的配置类继承了AbstractApplicationContext,您可以调用:

getEnvironment().setActiveProfiles("your_profile");

例如:

public class TestContext extends AnnotationConfigWebApplicationContext {

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

}

希望它有所帮助。

答案 1 :(得分:0)

OldContext1中执行静态块之前,OldContext2OldComponents似乎正在加载类并进行初始化。

虽然我无法解释为什么你的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(您可能想调查一种方法来保证这一点?)并且导入列表中的其他两个类应该具有他们需要的系统设置正确初始化。

希望这会有所帮助......

答案 2 :(得分:0)

你需要确保环境首先生效。这就是我的方式:

@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

答案 3 :(得分:0)

在类中使用@profile批注来加载如下配置

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

并在属性文件中或作为运行时参数设置属性spring.profiles.active的值