弹簧 - 多个型材处于活动状态

2022-09-01 02:30:27

我基本上在春天有一个豆子,我只想在2个配置文件处于活动状态时才激活它。基本上,它就像:

@Profile({"Tomcat", "Linux"})
public class AppConfigMongodbLinux{...}

@Profile({"Tomcat", "WindowsLocal"})
public class AppConfigMongodbWindowsLocal{...}

所以我希望当我使用时,它会尝试只使用,但它仍然尝试注册.-Dspring.profiles.active=Tomcat,WindowsLocalAppConfigMongodbWindowsLocalAppConfigMongodbLinux

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'appConfigMongodbLinux': Injection of autowired dependencies failed

是否可以仅在两个配置文件都处于活动状态时才注册 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}"

答案 1

Spring 版本 5.1 及更高版本提供了用于指定更复杂的配置文件字符串表达式的附加功能。在您的情况下,可以通过以下方式实现所需的功能:

@Profile({"Tomcat & Linux"})
@Configuration
public class AppConfigMongodbLinux {...}

有关详细信息,请阅读使用Spring参考文档中的@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.
            }
        }
    }
}

测试了春季5.1.2版本。


答案 2

遗憾的是,如果列出的任何配置文件处于活动状态,则会激活。有几种方法可以解决这个问题。@Profile

  • 将公共批注应用于顶级配置类,然后应用于嵌套配置类(或方法)。@Profile("Tomcat")@Profile("Windows")@Bean
  • 如果 Spring Boot 可以作为依赖项,请使用 @AllNestedConditions 创建一个注释,该注释是 AND 而不是 OR。

看起来,如果您使用的是Spring Boot自动配置类,那么您尝试做的事情将很容易编写;如果在应用程序生命周期的此阶段引入自动配置是可行的,我建议考虑一下。


推荐