From 419f92d38188ddb2473efbc919940cf310d2bb82 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 24 Sep 2019 11:13:35 +0100 Subject: [PATCH] Tune @ConditionalOnMissingBean for interface-based back off Previously, a number of usages of @ConditionalOnMissingBean prevented a bean that implements an auto-configured bean's "main" interface from causing the auto-configuration of the bean to back off. This would happen when @ConditionalOnMissingBean did not specify a type, the @Bean method returned the bean's concrete type, and that concreate type implements a "main" interface. This commit updates such usages of @ConditionalOnMissingBean to specify the "main" interface as the type of the bean that must be missing. This will allow, for example, the auto-configured MongoTemplate bean to back off when a MongoOperations bean is defined. Fixes gh-18101 --- .../boot/autoconfigure/amqp/RabbitAutoConfiguration.java | 3 ++- .../data/cassandra/CassandraDataAutoConfiguration.java | 3 ++- .../cassandra/CassandraReactiveDataAutoConfiguration.java | 3 ++- .../elasticsearch/ElasticsearchDataAutoConfiguration.java | 3 ++- .../data/mongo/MongoDbFactoryDependentConfiguration.java | 6 ++++-- .../data/mongo/MongoReactiveDataAutoConfiguration.java | 3 ++- .../boot/autoconfigure/jms/JmsAutoConfiguration.java | 6 ++++-- .../boot/autoconfigure/jooq/JooqAutoConfiguration.java | 2 +- .../mail/MailSenderPropertiesConfiguration.java | 3 ++- .../autoconfigure/sendgrid/SendGridAutoConfiguration.java | 3 ++- .../autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java | 3 ++- .../transaction/TransactionAutoConfiguration.java | 3 ++- .../web/servlet/error/ErrorMvcAutoConfiguration.java | 2 +- 13 files changed, 28 insertions(+), 15 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitAutoConfiguration.java index aa135e610c..b91883fb29 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitAutoConfiguration.java @@ -28,6 +28,7 @@ import org.springframework.amqp.rabbit.connection.ConnectionNameStrategy; import org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean; import org.springframework.amqp.rabbit.core.RabbitAdmin; import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate; +import org.springframework.amqp.rabbit.core.RabbitOperations; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.beans.factory.ObjectProvider; @@ -165,7 +166,7 @@ public class RabbitAutoConfiguration { @Bean @ConditionalOnSingleCandidate(ConnectionFactory.class) - @ConditionalOnMissingBean + @ConditionalOnMissingBean(RabbitOperations.class) public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { PropertyMapper map = PropertyMapper.get(); RabbitTemplate template = new RabbitTemplate(connectionFactory); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java index f952858581..e7af205a6c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java @@ -42,6 +42,7 @@ import org.springframework.data.cassandra.config.CassandraEntityClassScanner; import org.springframework.data.cassandra.config.CassandraSessionFactoryBean; import org.springframework.data.cassandra.config.SchemaAction; import org.springframework.data.cassandra.core.CassandraAdminOperations; +import org.springframework.data.cassandra.core.CassandraOperations; import org.springframework.data.cassandra.core.CassandraTemplate; import org.springframework.data.cassandra.core.convert.CassandraConverter; import org.springframework.data.cassandra.core.convert.CassandraCustomConversions; @@ -125,7 +126,7 @@ public class CassandraDataAutoConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(CassandraOperations.class) public CassandraTemplate cassandraTemplate(Session session, CassandraConverter converter) throws Exception { return new CassandraTemplate(session, converter); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraReactiveDataAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraReactiveDataAutoConfiguration.java index 731d5ffc4d..73dd986030 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraReactiveDataAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraReactiveDataAutoConfiguration.java @@ -29,6 +29,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.cassandra.ReactiveSession; import org.springframework.data.cassandra.ReactiveSessionFactory; +import org.springframework.data.cassandra.core.ReactiveCassandraOperations; import org.springframework.data.cassandra.core.ReactiveCassandraTemplate; import org.springframework.data.cassandra.core.convert.CassandraConverter; import org.springframework.data.cassandra.core.cql.session.DefaultBridgedReactiveSession; @@ -60,7 +61,7 @@ public class CassandraReactiveDataAutoConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(ReactiveCassandraOperations.class) public ReactiveCassandraTemplate reactiveCassandraTemplate(ReactiveSession reactiveCassandraSession, CassandraConverter converter) { return new ReactiveCassandraTemplate(reactiveCassandraSession, converter); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchDataAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchDataAutoConfiguration.java index 8d37e68a4e..10913ee1cd 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchDataAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchDataAutoConfiguration.java @@ -25,6 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter; @@ -49,7 +50,7 @@ import org.springframework.data.elasticsearch.repository.config.EnableElasticsea public class ElasticsearchDataAutoConfiguration { @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(ElasticsearchOperations.class) @ConditionalOnBean(Client.class) public ElasticsearchTemplate elasticsearchTemplate(Client client, ElasticsearchConverter converter) { try { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDbFactoryDependentConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDbFactoryDependentConfiguration.java index 66ebbf9010..be5957a52a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDbFactoryDependentConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDbFactoryDependentConfiguration.java @@ -29,6 +29,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; @@ -36,6 +37,7 @@ import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.gridfs.GridFsOperations; import org.springframework.data.mongodb.gridfs.GridFsTemplate; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -56,7 +58,7 @@ class MongoDbFactoryDependentConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(MongoOperations.class) public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter converter) { return new MongoTemplate(mongoDbFactory, converter); } @@ -72,7 +74,7 @@ class MongoDbFactoryDependentConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(GridFsOperations.class) public GridFsTemplate gridFsTemplate(MongoDbFactory mongoDbFactory, MongoTemplate mongoTemplate) { return new GridFsTemplate(new GridFsMongoDbFactory(mongoDbFactory, this.properties), mongoTemplate.getConverter()); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoReactiveDataAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoReactiveDataAutoConfiguration.java index cfdbb0f81d..8fe10748cb 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoReactiveDataAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoReactiveDataAutoConfiguration.java @@ -30,6 +30,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; +import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @@ -73,7 +74,7 @@ public class MongoReactiveDataAutoConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(ReactiveMongoOperations.class) public ReactiveMongoTemplate reactiveMongoTemplate(ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory, MongoConverter converter) { return new ReactiveMongoTemplate(reactiveMongoDatabaseFactory, converter); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java index 442828e3c7..f5a9518f5d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java @@ -34,7 +34,9 @@ import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.jms.core.JmsMessageOperations; import org.springframework.jms.core.JmsMessagingTemplate; +import org.springframework.jms.core.JmsOperations; import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.support.converter.MessageConverter; import org.springframework.jms.support.destination.DestinationResolver; @@ -71,7 +73,7 @@ public class JmsAutoConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(JmsOperations.class) @ConditionalOnSingleCandidate(ConnectionFactory.class) public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) { PropertyMapper map = PropertyMapper.get(); @@ -104,7 +106,7 @@ public class JmsAutoConfiguration { protected static class MessagingTemplateConfiguration { @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(JmsMessageOperations.class) @ConditionalOnSingleCandidate(JmsTemplate.class) public JmsMessagingTemplate jmsMessagingTemplate(JmsTemplate jmsTemplate) { return new JmsMessagingTemplate(jmsTemplate); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqAutoConfiguration.java index 978eee8e39..dc5a0d5839 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqAutoConfiguration.java @@ -64,7 +64,7 @@ import org.springframework.transaction.PlatformTransactionManager; public class JooqAutoConfiguration { @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(ConnectionProvider.class) public DataSourceConnectionProvider dataSourceConnectionProvider(DataSource dataSource) { return new DataSourceConnectionProvider(new TransactionAwareDataSourceProxy(dataSource)); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailSenderPropertiesConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailSenderPropertiesConfiguration.java index e2bab11413..02f5e9293d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailSenderPropertiesConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailSenderPropertiesConfiguration.java @@ -24,6 +24,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.mail.MailSender; +import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSenderImpl; /** @@ -44,7 +45,7 @@ class MailSenderPropertiesConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(JavaMailSender.class) public JavaMailSenderImpl mailSender() { JavaMailSenderImpl sender = new JavaMailSenderImpl(); applyProperties(sender); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/sendgrid/SendGridAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/sendgrid/SendGridAutoConfiguration.java index b47babb5d5..22b9614226 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/sendgrid/SendGridAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/sendgrid/SendGridAutoConfiguration.java @@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.sendgrid; import com.sendgrid.Client; import com.sendgrid.SendGrid; +import com.sendgrid.SendGridAPI; import org.apache.http.HttpHost; import org.apache.http.impl.client.HttpClientBuilder; @@ -50,7 +51,7 @@ public class SendGridAutoConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(SendGridAPI.class) public SendGrid sendGrid() { if (this.properties.isProxyConfigured()) { HttpHost proxy = new HttpHost(this.properties.getProxy().getHost(), this.properties.getProxy().getPort()); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java index 6f607da5e3..04730d3fff 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java @@ -29,6 +29,7 @@ import org.apache.commons.logging.LogFactory; import org.thymeleaf.dialect.IDialect; import org.thymeleaf.extras.java8time.dialect.Java8TimeDialect; import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect; +import org.thymeleaf.spring5.ISpringTemplateEngine; import org.thymeleaf.spring5.ISpringWebFluxTemplateEngine; import org.thymeleaf.spring5.SpringTemplateEngine; import org.thymeleaf.spring5.SpringWebFluxTemplateEngine; @@ -147,7 +148,7 @@ public class ThymeleafAutoConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(ISpringTemplateEngine.class) public SpringTemplateEngine templateEngine() { SpringTemplateEngine engine = new SpringTemplateEngine(); engine.setEnableSpringELCompiler(this.properties.isEnableSpringElCompiler()); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration.java index 5eb4dead03..3b887a8e46 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration.java @@ -35,6 +35,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.AbstractTransactionManagementConfiguration; import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.transaction.support.TransactionOperations; import org.springframework.transaction.support.TransactionTemplate; /** @@ -69,7 +70,7 @@ public class TransactionAutoConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(TransactionOperations.class) public TransactionTemplate transactionTemplate() { return new TransactionTemplate(this.transactionManager); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.java index 38be07e8cf..192b0ff6d0 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.java @@ -140,7 +140,7 @@ public class ErrorMvcAutoConfiguration { @Bean @ConditionalOnBean(DispatcherServlet.class) - @ConditionalOnMissingBean + @ConditionalOnMissingBean(ErrorViewResolver.class) public DefaultErrorViewResolver conventionErrorViewResolver() { return new DefaultErrorViewResolver(this.applicationContext, this.resourceProperties); }