Spring Boot 2.1 复制 reactiveMongoTemplate bean

Spring Boot 2.1 duplicate reactiveMongoTemplate bean

我有以下 Spring 启动 @Configuration class:

@Configuration
@EnableReactiveMongoRepositories
class MongoConfiguration : AbstractReactiveMongoConfiguration()
{
    override fun reactiveMongoClient() = MongoClients.create()

    override fun getDatabaseName() = "mydb"

    override fun customConversions(): MongoCustomConversions =
            MongoCustomConversions(listOf(ZonedDateTimeReadConverter(), ZonedDateTimeWriteConverter()))
}

应用程序无法启动,并记录此消息:

The bean 'reactiveMongoTemplate', defined in class path resource [org/springframework/boot/autoconfigure/data/mongo/MongoReactiveDataAutoConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [com/mypackage/MongoConfiguration.class] and overriding is disabled.

这让我很困惑,因为 MongoReactiveDataAutoConfiguration 中的 reactiveMongoTemplate ben 方法配置了 @ConditionalOnMissingBean

问题出在您已细分的 AbstractReactiveMongoConfiguration 中。它的 reactiveMongoTemplate @Bean 方法的签名声明它 returns ReactiveMongoOperations。在创建 bean 之前,这就是所有可用的类型信息,bean 工厂无法知道 bean 实际上是一个 ReactiveMongoTemplate 实例。结果,正在寻找 ReactiveMongoTemplate bean 的 @ConditionaOnMissingBean 没有找到,因此尝试定义这两个 bean。这应该在 Spring Data MongoDB 中修复,以便 AbstractReactiveMongoConfiguration 为其 bean 提供尽可能多的类型信息。我打开了 DATAMONGO-2355.

您可以通过更多地使用 Spring Boot 的自动配置来避免这个问题。您可以:

而不是子类化 AbstractReactiveMongoConfiguration
  1. 使用配置属性 spring.data.mongodb.database=mydb设置数据库。
  2. 使用自动配置的 MongoClient bean 而不是定义您自己的 bean。
  3. 定义您自己的 MongoCustomConversions bean,然后将使用该 bean 支持 Boot 否则会自动配置的 bean。

正如 Andy 的回答正确指出的那样,AbstractReactiveMongoConfiguration#reactiveMongoTemplate 的 return 类型与自动配置的 bean 之间存在不匹配:第一个是 ReactiveMongoOperations 而第二个是 ReactiveMongoTemplate。由于这恰好是 bean 工厂可用的唯一类型信息,因此 @ConditionalOnMissingBean 无效。

所以如果我简单地重写 AbstractReactiveMongoConfiguration#reactiveMongoTemplate 来缩小 return 类型,问题就消失了:

override fun reactiveMongoTemplate(): ReactiveMongoTemplate = 
        super.reactiveMongoTemplate() as ReactiveMongoTemplate

虽然这是一个 hack:当配置任何 ReactiveMongoOperations bean(例如存根)时,自动配置应该退出。

所以与 Andy 所说的相反,我认为问题不在 AbstractReactiveMongoConfiguration 而在 MongoReactiveDataAutoConfiguration,其中 reactiveMongoTemplate bean 方法应该用 @ConditionalOnMissingBean(ReactiveMongoOperations.class) 注释。

这可能被遗忘了,因为通常实际的 bean 是 ReactiveMongoTemplate。但是,如果 ReactiveMongoOperations 接口得不到正确支持,为什么还要使用它呢?