From 73a08dd6689dcb420541b13701aa448a995c95a5 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 10 Jul 2018 09:45:15 +0100 Subject: [PATCH] Avoid overriding beans and ensure import order is used for DataSource During processing of a configuration class, the class's complete hierarchy is processed and during the processing of each class its member classes are processed. Previously, each pool-specific inner-class of DataSourceConfiguration extended the abstract outer class. This meant that when the import from DataSourceAutoConfiguration.PooledDataSourceConfiguration caused the first pool-specific inner-class to be processed, DataSourceConfiguration would be processed as it was the inner-class's superclass. In turn all of DataSourceConfiguration's member classes would then be processed. This caused the first import (of DataSourceConfiguration.Tomcat) to trigger processing of all of the other pool-specific inner-classes in whatever order they were found rather than them being processed in the order in which they are imported by DataSourceAutoConfiguration.PooledDataSourceConfiguration. Another part of the problem was that none of the pool-specific inner-classes were conditional on a missing DataSource bean. This meant that, when multiple pools were on the classpath, each class after the first would override the previous class's definition of the DataSource bean. This commit updates each of the pool-specific inner-classes so that they no longer extend DataSourceConfiguration. This ensures that the inner classes are processed in the order defined in the import on PooledDataSourceConfiguration. Each of the classes has also been annotated with @ConditionalOnMissingBean(DataSource.class). This prevents the DataSource bean definition from being overridden and ensures that the order of precedence for the pool that will be used is as defined in the import. Closes gh-13737 --- .../jdbc/DataSourceConfiguration.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java index d8819c65b8..3c36b86b00 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,7 +37,7 @@ import org.springframework.context.annotation.Bean; abstract class DataSourceConfiguration { @SuppressWarnings("unchecked") - protected T createDataSource(DataSourceProperties properties, + protected static T createDataSource(DataSourceProperties properties, Class type) { return (T) properties.initializeDataSourceBuilder().type(type).build(); } @@ -46,8 +46,9 @@ abstract class DataSourceConfiguration { * Tomcat Pool DataSource configuration. */ @ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class) + @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true) - static class Tomcat extends DataSourceConfiguration { + static class Tomcat { @Bean @ConfigurationProperties(prefix = "spring.datasource.tomcat") @@ -71,8 +72,9 @@ abstract class DataSourceConfiguration { * Hikari DataSource configuration. */ @ConditionalOnClass(HikariDataSource.class) + @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true) - static class Hikari extends DataSourceConfiguration { + static class Hikari { @Bean @ConfigurationProperties(prefix = "spring.datasource.hikari") @@ -88,9 +90,10 @@ abstract class DataSourceConfiguration { * @deprecated as of 1.5 in favor of DBCP2 */ @ConditionalOnClass(org.apache.commons.dbcp.BasicDataSource.class) + @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.commons.dbcp.BasicDataSource", matchIfMissing = true) @Deprecated - static class Dbcp extends DataSourceConfiguration { + static class Dbcp { @Bean @ConfigurationProperties(prefix = "spring.datasource.dbcp") @@ -114,8 +117,9 @@ abstract class DataSourceConfiguration { * DBCP DataSource configuration. */ @ConditionalOnClass(org.apache.commons.dbcp2.BasicDataSource.class) + @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.commons.dbcp2.BasicDataSource", matchIfMissing = true) - static class Dbcp2 extends DataSourceConfiguration { + static class Dbcp2 { @Bean @ConfigurationProperties(prefix = "spring.datasource.dbcp2")