问题
I have the following Spring Boot @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 application fails to start, and logs this message:
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.
This puzzles me, as the reactiveMongoTemplate ben method in MongoReactiveDataAutoConfiguration is configured with @ConditionalOnMissingBean.
回答1:
The problem is in AbstractReactiveMongoConfiguration that you have sub-classed. The signature of its reactiveMongoTemplate @Bean method states that it returns ReactiveMongoOperations. Until the bean has been created, that's all the type information that is available and there is no way for the bean factory to know that the bean is actually a ReactiveMongoTemplate instance. As a result, the @ConditionaOnMissingBean that's looking for a ReactiveMongoTemplate bean doesn't find one so an attempt to define both beans is made. This should be fixed in Spring Data MongoDB so that AbstractReactiveMongoConfiguration provides as much type information as possible for its beans. I've opened DATAMONGO-2355.
You can avoid the problem by making more use of Spring Boot's auto-configuration. Rather than sub-classing AbstractReactiveMongoConfiguration you can:
- Use the configuration property
spring.data.mongodb.database=mydbto set the database. - Use the auto-configured
MongoClientbean rather than defining your own. - Define your own
MongoCustomConversionsbean that will then be used in favour of one that Boot would otherwise auto-configure.
回答2:
As Andy's answer correctly points out, there is a mismatch between the return type of AbstractReactiveMongoConfiguration#reactiveMongoTemplate and the autoconfigured bean: the first one is ReactiveMongoOperations while the second one is ReactiveMongoTemplate. And as this happens to be the only type info available to the bean factory, the @ConditionalOnMissingBean has no effect.
So the problem goes away if I simply override AbstractReactiveMongoConfiguration#reactiveMongoTemplate to narrow the return type like this:
override fun reactiveMongoTemplate(): ReactiveMongoTemplate =
super.reactiveMongoTemplate() as ReactiveMongoTemplate
This is a hack though: the autoconfiguration should back out when any ReactiveMongoOperations bean is configured (for example, a stub).
So contrary to what Andy says, I believe the problem is not in AbstractReactiveMongoConfiguration but in MongoReactiveDataAutoConfiguration where the reactiveMongoTemplate bean method should be annotated with @ConditionalOnMissingBean(ReactiveMongoOperations.class).
This was probably forgotten because normally the actual bean will be a ReactiveMongoTemplate. But why have the ReactiveMongoOperations interface at all if it's not supported properly?
来源:https://stackoverflow.com/questions/57761228/spring-boot-2-1-duplicate-reactivemongotemplate-bean