繁体   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