From 80b8f19961e39df76538fb252f5e962b834ad09c Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 6 Sep 2019 17:55:06 +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. --- .../boot/autoconfigure/amqp/RabbitAutoConfiguration.java | 3 ++- .../data/cassandra/CassandraDataAutoConfiguration.java | 3 ++- .../cassandra/CassandraReactiveDataAutoConfiguration.java | 3 ++- .../data/mongo/MongoDbFactoryDependentConfiguration.java | 6 ++++-- .../data/mongo/MongoReactiveDataAutoConfiguration.java | 8 +++++--- .../boot/autoconfigure/jms/JmsAutoConfiguration.java | 6 ++++-- .../boot/autoconfigure/jooq/JooqAutoConfiguration.java | 2 +- .../mail/MailSenderPropertiesConfiguration.java | 3 ++- .../autoconfigure/sendgrid/SendGridAutoConfiguration.java | 3 ++- .../thymeleaf/ThymeleafAutoConfiguration.java | 3 ++- .../transaction/TransactionAutoConfiguration.java | 3 ++- .../transaction/jta/AtomikosJtaConfiguration.java | 2 +- .../web/servlet/error/ErrorMvcAutoConfiguration.java | 2 +- 13 files changed, 30 insertions(+), 17 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 44e02746c3..a2a6f2f8a0 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; @@ -151,7 +152,7 @@ public class RabbitAutoConfiguration { @Bean @ConditionalOnSingleCandidate(ConnectionFactory.class) - @ConditionalOnMissingBean + @ConditionalOnMissingBean(RabbitOperations.class) public RabbitTemplate rabbitTemplate(RabbitProperties properties, ObjectProvider messageConverter, ObjectProvider retryTemplateCustomizers, 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 58a2a145a2..309da94409 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; @@ -118,7 +119,7 @@ public class CassandraDataAutoConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(CassandraOperations.class) public CassandraTemplate cassandraTemplate(Session session, CassandraConverter converter) { 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 ead486f683..2f0cd83589 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/mongo/MongoDbFactoryDependentConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDbFactoryDependentConfiguration.java index ba140d35ec..9c8e7d886a 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) MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter converter) { return new MongoTemplate(mongoDbFactory, converter); } @@ -72,7 +74,7 @@ class MongoDbFactoryDependentConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(GridFsOperations.class) 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 469b76a151..1dd45e93c0 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 @@ -32,6 +32,7 @@ import org.springframework.context.annotation.Import; import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DefaultDataBufferFactory; 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; @@ -39,6 +40,7 @@ import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.gridfs.ReactiveGridFsOperations; import org.springframework.data.mongodb.gridfs.ReactiveGridFsTemplate; /** @@ -72,7 +74,7 @@ public class MongoReactiveDataAutoConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(ReactiveMongoOperations.class) public ReactiveMongoTemplate reactiveMongoTemplate(ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory, MongoConverter converter) { return new ReactiveMongoTemplate(reactiveMongoDatabaseFactory, converter); @@ -88,13 +90,13 @@ public class MongoReactiveDataAutoConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(DataBufferFactory.class) public DefaultDataBufferFactory dataBufferFactory() { return new DefaultDataBufferFactory(); } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(ReactiveGridFsOperations.class) public ReactiveGridFsTemplate reactiveGridFsTemplate(ReactiveMongoDatabaseFactory reactiveMongoDbFactory, MappingMongoConverter mappingMongoConverter, DataBufferFactory dataBufferFactory) { return new ReactiveGridFsTemplate(dataBufferFactory, reactiveMongoDbFactory, mappingMongoConverter, null); 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 110134f954..2b662a836a 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(JmsProperties properties, JmsTemplate jmsTemplate) { JmsMessagingTemplate messagingTemplate = 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 327e66c744..da2f9265c0 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 3ac8ffa77c..5c5bd79594 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; /** @@ -38,7 +39,7 @@ import org.springframework.mail.javamail.JavaMailSenderImpl; class MailSenderPropertiesConfiguration { @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(JavaMailSender.class) JavaMailSenderImpl mailSender(MailProperties properties) { JavaMailSenderImpl sender = new JavaMailSenderImpl(); applyProperties(properties, 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 bd187be5c8..171137ab75 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; @@ -44,7 +45,7 @@ import org.springframework.context.annotation.Configuration; public class SendGridAutoConfiguration { @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(SendGridAPI.class) public SendGrid sendGrid(SendGridProperties properties) { if (properties.isProxyConfigured()) { HttpHost proxy = new HttpHost(properties.getProxy().getHost(), 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 ad19a5bc68..b1ab53974b 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 @@ -28,6 +28,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; @@ -133,7 +134,7 @@ public class ThymeleafAutoConfiguration { protected static class ThymeleafDefaultConfiguration { @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(ISpringTemplateEngine.class) SpringTemplateEngine templateEngine(ThymeleafProperties properties, ObjectProvider templateResolvers, ObjectProvider dialects) { SpringTemplateEngine engine = new SpringTemplateEngine(); 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 12257d7f3e..e729e7bf8c 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; /** @@ -63,7 +64,7 @@ public class TransactionAutoConfiguration { public static class TransactionTemplateConfiguration { @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(TransactionOperations.class) public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) { return new TransactionTemplate(transactionManager); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java index 5bf7a27be3..abd3cd7084 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java @@ -82,7 +82,7 @@ class AtomikosJtaConfiguration { } @Bean(initMethod = "init", destroyMethod = "close") - @ConditionalOnMissingBean + @ConditionalOnMissingBean(TransactionManager.class) UserTransactionManager atomikosTransactionManager(UserTransactionService userTransactionService) throws Exception { UserTransactionManager manager = new UserTransactionManager(); manager.setStartupTransactionService(false); 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 35d12435ba..458fc3de8d 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 @@ -136,7 +136,7 @@ public class ErrorMvcAutoConfiguration { @Bean @ConditionalOnBean(DispatcherServlet.class) - @ConditionalOnMissingBean + @ConditionalOnMissingBean(ErrorViewResolver.class) DefaultErrorViewResolver conventionErrorViewResolver() { return new DefaultErrorViewResolver(this.applicationContext, this.resourceProperties); }