Commit 73a08dd6 authored by Andy Wilkinson's avatar Andy Wilkinson

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
parent 8b2cb32a
/*
* 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> T createDataSource(DataSourceProperties properties,
protected static <T> T createDataSource(DataSourceProperties properties,
Class<? extends DataSource> 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")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment