java - @ConditionalOnMissingBean 和 @ConditionalOnBean 位于同一类型上

标签 java spring spring-boot

我遇到了奇怪的情况。我正在尝试编写自动配置类,如果另一个 bean 存在或不存在,我会在其中创建 bean,因此我对 bean 有条件,并且对相同类型的缺少 bean 有条件。

这是我的代码:

@Bean
@ConditionalOnMissingBean(
    type = {"com.example.Api"}
)
public ApiManager apiManager() {
    return new ApiManager() {
        public Result getValue(Request request) {
            throw new Exception("Api not provided.");
        }

        public Result setValue(Request request) {
            throw new Exception("Api not provided.");
        }
    };
}

@Bean
@ConditionalOnBean(
    type = {"com.example.Api"}
)
public ApiManager apiManager(Api api) {
    return new ApiManagerImpl(api);
}

问题是,如果它已经在@ConditionalOnMissingBean中检查了com.example.Api类型的bean,它就不会检查@ConditionalOnBean没有丢失,则不会创建 bean。

我收到如下错误:

Parameter 2 of constructor in com.example.ServiceImpl required a bean of type 'com.example.ApiManager' that could not be found.
- Bean method 'apiManager' in 'ApiAutoConfiguration' not loaded because @ConditionalOnMissingBean (types: com.example.Api; SearchStrategy: all) found bean 'api'
- Bean method 'apiManager' in 'ApiAutoConfiguration' not loaded because @ConditionalOnMissingBean (types: com.example.Api; SearchStrategy: all) found bean 'api'

最佳答案

你得到的结果是非常合乎逻辑的。条件按顺序评估,这就是为什么在用户配置之后处理自动配置的原因。

如果上下文符合您的预期,我们必须在执行任何操作之前评估所有 bean 定义的所有条件。这将违背自动配置处理用户(用户配置)或自动配置提供的某种类型的 bean 的目的。

您需要重写此自动配置才能按顺序导入内容。一种方法是将每个方法移动到包私有(private)配置类上,然后执行以下操作:

@Configuration
@Import({ApiPresentConfiguration.class, ApiNotPresentConfiguration.class})

处理这个问题的更好方法是根本不这样做,而简单地使用 ObjectProvider:

@Bean
public ApiManager apiManager(ObjectProvider<Api> api) {
    // Check if API is present and then return the appropriate implementation
}

关于java - @ConditionalOnMissingBean 和 @ConditionalOnBean 位于同一类型上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55594600/

相关文章:

spring-boot - Spring Data MongoRepository 保存导致重复键错误

java - 这段代码是适配器模式的示例吗?

java - Dagger2组件初始化

java - "positive"收到用户请求时进行缓存 - ehcache

java - JAssert 库未纳入 Spring Boot 测试

java - 什么是用于 Spring Boot 日志记录的默认 CONSOLE_LOG_PATTERN 以及在哪里可以找到它?

java - OS X gzip 可以配置为匹配 Java GZIPOutputStream 吗?

java - 如何减少InputStreams和OutputStreams之间的写入?

java - Mybatis - 没有任何错误,它只是返回 [] 而不是数据库数据

java - 自定义注释不验证方法参数