[英]Spring - Multiple Profiles active
我基本上在 Spring 中有一个 bean,我只想在 2 个配置文件处于活动状态时激活它。 基本上,它会是这样的:
@Profile({"Tomcat", "Linux"})
public class AppConfigMongodbLinux{...}
@Profile({"Tomcat", "WindowsLocal"})
public class AppConfigMongodbWindowsLocal{...}
所以我希望当我使用-Dspring.profiles.active=Tomcat,WindowsLocal
,它会尝试只使用AppConfigMongodbWindowsLocal
,但它仍然尝试注册AppConfigMongodbLinux
。
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'appConfigMongodbLinux': Injection of autowired dependencies failed
是否可以仅在两个配置文件都处于活动状态时才注册 bean,或者我是否错误地使用了它? :)
谢谢!!
编辑:发布完整堆栈。
错误实际上是在属性中缺少的属性上,但是这个 bean 会被激活吗? 我想了解这一点以确保我没有激活错误的 bean..
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]]
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'appConfigMongodbLinux': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.Integer mycompany.config.AppConfigMongodbLinux.mongoPort; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'mongo.port' in string value "${mongo.port}"
... 40 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.Integer mycompany.config.AppConfigMongodbLinux.mongoPort; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'mongo.port' in string value "${mongo.port}"
...
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'mongo.port' in string value "${mongo.port}"
Spring 5.1及更高版本提供了用于指定更复杂的配置文件字符串表达式的附加功能。 在您的情况下,可以通过以下方式实现所需的功能:
@Profile({"Tomcat & Linux"})
@Configuration
public class AppConfigMongodbLinux {...}
请阅读 Spring 参考文档中的Using @Profile章节以获取更多信息。
更新(方法级配置文件表达式):实际上我已经测试了一些 @Bean 方法级配置文件表达式,一切都像魅力一样:
/**
* Shows basic usage of {@link Profile} annotations applied on method level.
*/
@Configuration
public class MethodLevelProfileConfiguration {
/**
* Point in time related to application startup.
*/
@Profile("qa")
@Bean
public Instant startupInstant() {
return Instant.now();
}
/**
* Point in time related to scheduled shutdown of the application.
*/
@Bean
public Instant shutdownInstant() {
return Instant.MAX;
}
/**
* Point in time of 1970 year.
*/
@Profile("develop & production")
@Bean
public Instant epochInstant() {
return Instant.EPOCH;
}
}
集成测试:
/**
* Verifies {@link Profile} annotation functionality applied on method-level.
*/
public class MethodLevelProfileConfigurationTest {
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MethodLevelProfileConfiguration.class)
@ActiveProfiles(profiles = "qa")
public static class QaActiveProfileTest {
@Autowired
private ApplicationContext context;
@Test
public void shouldRegisterStartupAndShutdownInstants() {
context.getBean("startupInstant", Instant.class);
context.getBean("shutdownInstant", Instant.class);
try {
context.getBean("epochInstant", Instant.class);
fail();
} catch (NoSuchBeanDefinitionException ex) {
// Legal to ignore.
}
}
}
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MethodLevelProfileConfiguration.class)
@ActiveProfiles(profiles = {"develop", "production"})
public static class MethodProfileExpressionTest {
@Autowired
private ApplicationContext context;
@Test
public void shouldRegisterShutdownAndEpochInstants() {
context.getBean("epochInstant", Instant.class);
context.getBean("shutdownInstant", Instant.class);
try {
context.getBean("startupInstant", Instant.class);
fail();
} catch (NoSuchBeanDefinitionException ex) {
// Legal to ignore.
}
}
}
}
Spring 5.1.2 版本已测试。
不幸的是, @Profile
激活如有上市配置被激活。 有几种方法可以解决这个问题。
@Profile("Tomcat")
注释应用于顶级配置类,然后将@Profile("Windows")
应用于嵌套的配置类(或@Bean
方法)。@AllNestedConditions
创建一个注释,即 AND 而不是 OR。如果您使用 Spring Boot 自动配置类,看起来您尝试做的事情写起来很干净; 如果在应用程序生命周期的这个阶段引入自动配置是可行的,我建议考虑它。
@ConditionalOnExpression("#{environment.acceptsProfiles('Tomcat') && environment.acceptsProfiles('Linux')}")
致谢:Spring 源代码。 使用您的 IDE 查找 @ConditionalOnExpression,然后“查找用法”以查看源代码中的相关示例。 这将使您成为更好的开发人员。
第一个配置文件位于顶级。 第二个我是这样检查的:
@Autowired
private Environment env;
...
final boolean isMyProfile = Arrays.stream(env.getActiveProfiles()).anyMatch("MyProfile"::equals);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.