Add a generic to DataSourceBuilder

Closes gh-7942
pull/9635/head
Andy Wilkinson 7 years ago
parent 16edf72faa
commit bb3f32fa2b

@ -131,8 +131,8 @@ public class DataSourceAutoConfiguration {
* @return the class loader * @return the class loader
*/ */
private ClassLoader getDataSourceClassLoader(ConditionContext context) { private ClassLoader getDataSourceClassLoader(ConditionContext context) {
Class<?> dataSourceClass = new DataSourceBuilder(context.getClassLoader()) Class<?> dataSourceClass = DataSourceBuilder
.findType(); .findType(context.getClassLoader());
return (dataSourceClass == null ? null : dataSourceClass.getClassLoader()); return (dataSourceClass == null ? null : dataSourceClass.getClassLoader());
} }

@ -180,7 +180,7 @@ public class DataSourceProperties
* @return a {@link DataSourceBuilder} initialized with the customizations defined on * @return a {@link DataSourceBuilder} initialized with the customizations defined on
* this instance * this instance
*/ */
public DataSourceBuilder initializeDataSourceBuilder() { public DataSourceBuilder<?> initializeDataSourceBuilder() {
return DataSourceBuilder.create(getClassLoader()).type(getType()) return DataSourceBuilder.create(getClassLoader()).type(getType())
.driverClassName(determineDriverClassName()).url(determineUrl()) .driverClassName(determineDriverClassName()).url(determineUrl())
.username(determineUsername()).password(determinePassword()); .username(determineUsername()).password(determinePassword());

@ -51,8 +51,8 @@ public class ConfigurableDataSourceExample {
@Bean @Bean
@ConfigurationProperties("app.datasource") @ConfigurationProperties("app.datasource")
public HikariDataSource dataSource(DataSourceProperties properties) { public HikariDataSource dataSource(DataSourceProperties properties) {
return (HikariDataSource) properties.initializeDataSourceBuilder() return properties.initializeDataSourceBuilder().type(HikariDataSource.class)
.type(HikariDataSource.class).build(); .build();
} }
// end::configuration[] // end::configuration[]

@ -41,8 +41,7 @@ public class SimpleDataSourceExample {
@Bean @Bean
@ConfigurationProperties("app.datasource") @ConfigurationProperties("app.datasource")
public HikariDataSource dataSource() { public HikariDataSource dataSource() {
return (HikariDataSource) DataSourceBuilder.create() return DataSourceBuilder.create().type(HikariDataSource.class).build();
.type(HikariDataSource.class).build();
} }
// end::configuration[] // end::configuration[]

@ -58,8 +58,7 @@ public class SimpleTwoDataSourcesExample {
@Bean @Bean
@ConfigurationProperties("app.datasource.bar") @ConfigurationProperties("app.datasource.bar")
public BasicDataSource barDataSource() { public BasicDataSource barDataSource() {
return (BasicDataSource) DataSourceBuilder.create() return DataSourceBuilder.create().type(BasicDataSource.class).build();
.type(BasicDataSource.class).build();
} }
// end::configuration[] // end::configuration[]

@ -39,11 +39,12 @@ import org.springframework.util.ClassUtils;
* inject additional properties into the result you can downcast it, or use * inject additional properties into the result you can downcast it, or use
* {@code @ConfigurationProperties}. * {@code @ConfigurationProperties}.
* *
* @param <T> type of DataSource produced by the builder
* @author Dave Syer * @author Dave Syer
* @author Madhura Bhave * @author Madhura Bhave
* @since 2.0.0 * @since 2.0.0
*/ */
public class DataSourceBuilder { public final class DataSourceBuilder<T extends DataSource> {
private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] { private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] {
"com.zaxxer.hikari.HikariDataSource", "com.zaxxer.hikari.HikariDataSource",
@ -56,24 +57,25 @@ public class DataSourceBuilder {
private Map<String, String> properties = new HashMap<>(); private Map<String, String> properties = new HashMap<>();
public static DataSourceBuilder create() { public static DataSourceBuilder<?> create() {
return new DataSourceBuilder(null); return new DataSourceBuilder<DataSource>(null);
} }
public static DataSourceBuilder create(ClassLoader classLoader) { public static DataSourceBuilder<?> create(ClassLoader classLoader) {
return new DataSourceBuilder(classLoader); return new DataSourceBuilder<DataSource>(classLoader);
} }
public DataSourceBuilder(ClassLoader classLoader) { private DataSourceBuilder(ClassLoader classLoader) {
this.classLoader = classLoader; this.classLoader = classLoader;
} }
public DataSource build() { @SuppressWarnings("unchecked")
public T build() {
Class<? extends DataSource> type = getType(); Class<? extends DataSource> type = getType();
DataSource result = BeanUtils.instantiateClass(type); DataSource result = BeanUtils.instantiateClass(type);
maybeGetDriverClassName(); maybeGetDriverClassName();
bind(result); bind(result);
return result; return (T) result;
} }
private void maybeGetDriverClassName() { private void maybeGetDriverClassName() {
@ -95,40 +97,38 @@ public class DataSourceBuilder {
binder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(result)); binder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(result));
} }
public DataSourceBuilder type(Class<? extends DataSource> type) { @SuppressWarnings("unchecked")
public <D extends DataSource> DataSourceBuilder<D> type(Class<D> type) {
this.type = type; this.type = type;
return this; return (DataSourceBuilder<D>) this;
} }
public DataSourceBuilder url(String url) { public DataSourceBuilder<T> url(String url) {
this.properties.put("url", url); this.properties.put("url", url);
return this; return this;
} }
public DataSourceBuilder driverClassName(String driverClassName) { public DataSourceBuilder<T> driverClassName(String driverClassName) {
this.properties.put("driverClassName", driverClassName); this.properties.put("driverClassName", driverClassName);
return this; return this;
} }
public DataSourceBuilder username(String username) { public DataSourceBuilder<T> username(String username) {
this.properties.put("username", username); this.properties.put("username", username);
return this; return this;
} }
public DataSourceBuilder password(String password) { public DataSourceBuilder<T> password(String password) {
this.properties.put("password", password); this.properties.put("password", password);
return this; return this;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Class<? extends DataSource> findType() { public static Class<? extends DataSource> findType(ClassLoader classLoader) {
if (this.type != null) {
return this.type;
}
for (String name : DATA_SOURCE_TYPE_NAMES) { for (String name : DATA_SOURCE_TYPE_NAMES) {
try { try {
return (Class<? extends DataSource>) ClassUtils.forName(name, return (Class<? extends DataSource>) ClassUtils.forName(name,
this.classLoader); classLoader);
} }
catch (Exception ex) { catch (Exception ex) {
// Swallow and continue // Swallow and continue
@ -138,7 +138,8 @@ public class DataSourceBuilder {
} }
private Class<? extends DataSource> getType() { private Class<? extends DataSource> getType() {
Class<? extends DataSource> type = findType(); Class<? extends DataSource> type = this.type != null ? this.type
: findType(this.classLoader);
if (type != null) { if (type != null) {
return type; return type;
} }

@ -71,6 +71,13 @@ public class DataSourceBuilderTests {
assertThat(this.dataSource).isInstanceOf(BasicDataSource.class); assertThat(this.dataSource).isInstanceOf(BasicDataSource.class);
} }
@Test
public void specificTypeOfDataSource() {
HikariDataSource hikariDataSource = DataSourceBuilder.create().type(HikariDataSource.class)
.build();
assertThat(hikariDataSource).isInstanceOf(HikariDataSource.class);
}
final class HidePackagesClassLoader extends URLClassLoader { final class HidePackagesClassLoader extends URLClassLoader {
private final String[] hiddenPackages; private final String[] hiddenPackages;

@ -86,7 +86,7 @@ public abstract class AbstractDataSourcePoolMetadataTests<D extends AbstractData
@Test @Test
public abstract void getValidationQuery(); public abstract void getValidationQuery();
protected DataSourceBuilder initializeBuilder() { protected DataSourceBuilder<?> initializeBuilder() {
return DataSourceBuilder.create().driverClassName("org.hsqldb.jdbc.JDBCDriver") return DataSourceBuilder.create().driverClassName("org.hsqldb.jdbc.JDBCDriver")
.url("jdbc:hsqldb:mem:test").username("sa"); .url("jdbc:hsqldb:mem:test").username("sa");
} }

@ -90,7 +90,7 @@ public class CommonsDbcp2DataSourcePoolMetadataTests
} }
private BasicDataSource createDataSource() { private BasicDataSource createDataSource() {
return (BasicDataSource) initializeBuilder().type(BasicDataSource.class).build(); return initializeBuilder().type(BasicDataSource.class).build();
} }
} }

@ -51,8 +51,8 @@ public class HikariDataSourcePoolMetadataTests
} }
private HikariDataSource createDataSource(int minSize, int maxSize) { private HikariDataSource createDataSource(int minSize, int maxSize) {
HikariDataSource dataSource = (HikariDataSource) initializeBuilder() HikariDataSource dataSource = initializeBuilder().type(HikariDataSource.class)
.type(HikariDataSource.class).build(); .build();
dataSource.setMinimumIdle(minSize); dataSource.setMinimumIdle(minSize);
dataSource.setMaximumPoolSize(maxSize); dataSource.setMaximumPoolSize(maxSize);
return dataSource; return dataSource;

@ -51,8 +51,7 @@ public class TomcatDataSourcePoolMetadataTests
} }
private DataSource createDataSource(int minSize, int maxSize) { private DataSource createDataSource(int minSize, int maxSize) {
DataSource dataSource = (DataSource) initializeBuilder().type(DataSource.class) DataSource dataSource = initializeBuilder().type(DataSource.class).build();
.build();
dataSource.setMinIdle(minSize); dataSource.setMinIdle(minSize);
dataSource.setMaxActive(maxSize); dataSource.setMaxActive(maxSize);

Loading…
Cancel
Save