4

在我正在处理的一个项目中,我们有一些旧的依赖项,它们定义了自己的 spring bean,但需要从主应用程序初始化。这些bean都是使用spring配置文件构建的,即生产代码的“默认”和测试代码的“测试”。我们希望不再使用弹簧配置文件,而是简单地使用 @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

4 回答 4

0

显然,在执行静态块之前,OldContext1并且OldContext2正在类加载和初始化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则应首先加载类(您可能想研究一种保证这一点的方法?)并且导入列表中的其他两个类应该具有它们需要正确初始化的系统设置。

希望这可以帮助...

于 2013-10-10T10:36:41.283 回答
0

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

getEnvironment().setActiveProfiles("your_profile");

例如:

public class TestContext extends AnnotationConfigWebApplicationContext {

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

}

希望能帮助到你。

于 2013-10-09T14:53:23.817 回答
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
于 2016-09-05T09:10:22.720 回答
0

在类中使用@profile 注解来加载配置,如下所示

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

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

于 2018-07-25T12:16:54.663 回答