Add JdbcTemplate only on single DataSource
Update auto-configuration logic so that a `JdbcTemplate` is only added when there is a single candidate DataSource bean. Closes gh-6449
This commit is contained in:
		
							parent
							
								
									e0adacbeae
								
							
						
					
					
						commit
						5ecb68b226
					
				|  | @ -47,10 +47,6 @@ import org.springframework.context.annotation.Import; | |||
| import org.springframework.core.Ordered; | ||||
| import org.springframework.core.annotation.Order; | ||||
| import org.springframework.core.type.AnnotatedTypeMetadata; | ||||
| import org.springframework.jdbc.core.JdbcOperations; | ||||
| import org.springframework.jdbc.core.JdbcTemplate; | ||||
| import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; | ||||
| import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; | ||||
| import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; | ||||
| 
 | ||||
| /** | ||||
|  | @ -108,29 +104,6 @@ public class DataSourceAutoConfiguration { | |||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	@Configuration | ||||
| 	@Conditional(DataSourceAutoConfiguration.DataSourceAvailableCondition.class) | ||||
| 	protected static class JdbcTemplateConfiguration { | ||||
| 
 | ||||
| 		private final DataSource dataSource; | ||||
| 
 | ||||
| 		public JdbcTemplateConfiguration(DataSource dataSource) { | ||||
| 			this.dataSource = dataSource; | ||||
| 		} | ||||
| 
 | ||||
| 		@Bean | ||||
| 		@ConditionalOnMissingBean(JdbcOperations.class) | ||||
| 		public JdbcTemplate jdbcTemplate() { | ||||
| 			return new JdbcTemplate(this.dataSource); | ||||
| 		} | ||||
| 
 | ||||
| 		@Bean | ||||
| 		@ConditionalOnMissingBean(NamedParameterJdbcOperations.class) | ||||
| 		public NamedParameterJdbcTemplate namedParameterJdbcTemplate() { | ||||
| 			return new NamedParameterJdbcTemplate(this.dataSource); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@Configuration | ||||
| 	@ConditionalOnProperty(prefix = "spring.datasource", name = "jmx-enabled") | ||||
| 	@ConditionalOnClass(name = "org.apache.tomcat.jdbc.pool.DataSourceProxy") | ||||
|  |  | |||
|  | @ -0,0 +1,67 @@ | |||
| /* | ||||
|  * Copyright 2012-2016 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. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *      http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| package org.springframework.boot.autoconfigure.jdbc; | ||||
| 
 | ||||
| import javax.sql.DataSource; | ||||
| 
 | ||||
| import org.springframework.boot.autoconfigure.AutoConfigureAfter; | ||||
| import org.springframework.boot.autoconfigure.EnableAutoConfiguration; | ||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | ||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| import org.springframework.jdbc.core.JdbcOperations; | ||||
| import org.springframework.jdbc.core.JdbcTemplate; | ||||
| import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; | ||||
| import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; | ||||
| 
 | ||||
| /** | ||||
|  * {@link EnableAutoConfiguration Auto-configuration} for {@link JdbcTemplate} and | ||||
|  * {@link NamedParameterJdbcTemplate}. | ||||
|  * | ||||
|  * @author Dave Syer | ||||
|  * @author Phillip Webb | ||||
|  * @author Stephane Nicoll | ||||
|  * @author Kazuki Shimizu | ||||
|  * @since 1.4.0 | ||||
|  */ | ||||
| @Configuration | ||||
| @ConditionalOnClass(DataSource.class) | ||||
| @ConditionalOnSingleCandidate(DataSource.class) | ||||
| @AutoConfigureAfter(DataSourceAutoConfiguration.class) | ||||
| public class JdbcTemplateAutoConfiguration { | ||||
| 
 | ||||
| 	private final DataSource dataSource; | ||||
| 
 | ||||
| 	public JdbcTemplateAutoConfiguration(DataSource dataSource) { | ||||
| 		this.dataSource = dataSource; | ||||
| 	} | ||||
| 
 | ||||
| 	@Bean | ||||
| 	@ConditionalOnMissingBean(JdbcOperations.class) | ||||
| 	public JdbcTemplate jdbcTemplate() { | ||||
| 		return new JdbcTemplate(this.dataSource); | ||||
| 	} | ||||
| 
 | ||||
| 	@Bean | ||||
| 	@ConditionalOnMissingBean(NamedParameterJdbcOperations.class) | ||||
| 	public NamedParameterJdbcTemplate namedParameterJdbcTemplate() { | ||||
| 		return new NamedParameterJdbcTemplate(this.dataSource); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  | @ -49,6 +49,7 @@ org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\ | |||
| org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\ | ||||
| org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\ | ||||
| org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ | ||||
| org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\ | ||||
| org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\ | ||||
| org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\ | ||||
| org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\ | ||||
|  |  | |||
|  | @ -42,8 +42,6 @@ import org.springframework.boot.test.util.EnvironmentTestUtils; | |||
| import org.springframework.context.annotation.AnnotationConfigApplicationContext; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| import org.springframework.jdbc.core.JdbcTemplate; | ||||
| import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; | ||||
| 
 | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
| import static org.mockito.Mockito.mock; | ||||
|  | @ -228,35 +226,6 @@ public class DataSourceAutoConfigurationTests { | |||
| 		assertThat(dataSource).isInstanceOf(BasicDataSource.class); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testJdbcTemplateExists() throws Exception { | ||||
| 		this.context.register(DataSourceAutoConfiguration.class, | ||||
| 				PropertyPlaceholderAutoConfiguration.class); | ||||
| 		this.context.refresh(); | ||||
| 		JdbcTemplate jdbcTemplate = this.context.getBean(JdbcTemplate.class); | ||||
| 		assertThat(jdbcTemplate).isNotNull(); | ||||
| 		assertThat(jdbcTemplate.getDataSource()).isNotNull(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testJdbcTemplateExistsWithCustomDataSource() throws Exception { | ||||
| 		this.context.register(TestDataSourceConfiguration.class, | ||||
| 				DataSourceAutoConfiguration.class, | ||||
| 				PropertyPlaceholderAutoConfiguration.class); | ||||
| 		this.context.refresh(); | ||||
| 		JdbcTemplate jdbcTemplate = this.context.getBean(JdbcTemplate.class); | ||||
| 		assertThat(jdbcTemplate).isNotNull(); | ||||
| 		assertThat(jdbcTemplate.getDataSource() instanceof BasicDataSource).isTrue(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testNamedParameterJdbcTemplateExists() throws Exception { | ||||
| 		this.context.register(DataSourceAutoConfiguration.class, | ||||
| 				PropertyPlaceholderAutoConfiguration.class); | ||||
| 		this.context.refresh(); | ||||
| 		assertThat(this.context.getBean(NamedParameterJdbcOperations.class)).isNotNull(); | ||||
| 	} | ||||
| 
 | ||||
| 	@SuppressWarnings("unchecked") | ||||
| 	private <T extends DataSource> T autoConfigureDataSource(Class<T> expectedType, | ||||
| 			final String... hiddenPackages) { | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ import org.junit.After; | |||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import org.springframework.beans.factory.UnsatisfiedDependencyException; | ||||
| import org.springframework.beans.factory.BeanCreationException; | ||||
| import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; | ||||
| import org.springframework.boot.context.properties.ConfigurationProperties; | ||||
| import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||||
|  | @ -223,7 +223,7 @@ public class DataSourceInitializerTests { | |||
| 			fail("User does not exist"); | ||||
| 		} | ||||
| 		catch (Exception ex) { | ||||
| 			assertThat(ex).isInstanceOf(UnsatisfiedDependencyException.class); | ||||
| 			assertThat(ex).isInstanceOf(BeanCreationException.class); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | @ -245,7 +245,7 @@ public class DataSourceInitializerTests { | |||
| 			fail("User does not exist"); | ||||
| 		} | ||||
| 		catch (Exception ex) { | ||||
| 			assertThat(ex).isInstanceOf(UnsatisfiedDependencyException.class); | ||||
| 			assertThat(ex).isInstanceOf(BeanCreationException.class); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,164 @@ | |||
| /* | ||||
|  * Copyright 2012-2016 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. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *      http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| package org.springframework.boot.autoconfigure.jdbc; | ||||
| 
 | ||||
| import java.util.Random; | ||||
| 
 | ||||
| import javax.sql.DataSource; | ||||
| 
 | ||||
| import org.apache.commons.dbcp.BasicDataSource; | ||||
| import org.junit.After; | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; | ||||
| import org.springframework.boot.test.util.EnvironmentTestUtils; | ||||
| import org.springframework.context.annotation.AnnotationConfigApplicationContext; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| import org.springframework.jdbc.core.JdbcOperations; | ||||
| import org.springframework.jdbc.core.JdbcTemplate; | ||||
| import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; | ||||
| import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; | ||||
| 
 | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
| 
 | ||||
| /** | ||||
|  * Tests for {@link DataSourceAutoConfiguration}. | ||||
|  * | ||||
|  * @author Dave Syer | ||||
|  * @author Stephane Nicoll | ||||
|  * @author Kazuki Shimizu | ||||
|  * @since 1.4.0 | ||||
|  */ | ||||
| public class JdbcTemplateAutoConfigurationTests { | ||||
| 
 | ||||
| 	private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); | ||||
| 
 | ||||
| 	@Before | ||||
| 	public void init() { | ||||
| 		EmbeddedDatabaseConnection.override = null; | ||||
| 		EnvironmentTestUtils.addEnvironment(this.context, | ||||
| 				"spring.datasource.initialize:false", | ||||
| 				"spring.datasource.url:jdbc:hsqldb:mem:testdb-" + new Random().nextInt()); | ||||
| 	} | ||||
| 
 | ||||
| 	@After | ||||
| 	public void restore() { | ||||
| 		EmbeddedDatabaseConnection.override = null; | ||||
| 		this.context.close(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testJdbcTemplateExists() throws Exception { | ||||
| 		this.context.register(DataSourceAutoConfiguration.class, | ||||
| 				JdbcTemplateAutoConfiguration.class, | ||||
| 				PropertyPlaceholderAutoConfiguration.class); | ||||
| 		this.context.refresh(); | ||||
| 		JdbcTemplate jdbcTemplate = this.context.getBean(JdbcTemplate.class); | ||||
| 		assertThat(jdbcTemplate).isNotNull(); | ||||
| 		assertThat(jdbcTemplate.getDataSource()).isNotNull(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testJdbcTemplateExistsWithCustomDataSource() throws Exception { | ||||
| 		this.context.register(TestDataSourceConfiguration.class, | ||||
| 				DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class, | ||||
| 				PropertyPlaceholderAutoConfiguration.class); | ||||
| 		this.context.refresh(); | ||||
| 		JdbcTemplate jdbcTemplate = this.context.getBean(JdbcTemplate.class); | ||||
| 		assertThat(jdbcTemplate).isNotNull(); | ||||
| 		assertThat(jdbcTemplate.getDataSource() instanceof BasicDataSource).isTrue(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testNamedParameterJdbcTemplateExists() throws Exception { | ||||
| 		this.context.register(DataSourceAutoConfiguration.class, | ||||
| 				JdbcTemplateAutoConfiguration.class, | ||||
| 				PropertyPlaceholderAutoConfiguration.class); | ||||
| 		this.context.refresh(); | ||||
| 		assertThat(this.context.getBean(NamedParameterJdbcOperations.class)).isNotNull(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testMultiDataSource() throws Exception { | ||||
| 		this.context.register(MultiDataSourceConfiguration.class, | ||||
| 				DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class, | ||||
| 				PropertyPlaceholderAutoConfiguration.class); | ||||
| 		this.context.refresh(); | ||||
| 		assertThat(this.context.getBeansOfType(JdbcOperations.class)).isEmpty(); | ||||
| 		assertThat(this.context.getBeansOfType(NamedParameterJdbcOperations.class)) | ||||
| 				.isEmpty(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testMultiDataSourceUsingPrimary() throws Exception { | ||||
| 		this.context.register(MultiDataSourceUsingPrimaryConfiguration.class, | ||||
| 				DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class, | ||||
| 				PropertyPlaceholderAutoConfiguration.class); | ||||
| 		this.context.refresh(); | ||||
| 		assertThat(this.context.getBean(JdbcOperations.class)).isNotNull(); | ||||
| 		assertThat(this.context.getBean(NamedParameterJdbcOperations.class)).isNotNull(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testExistingCustomJdbcTemplate() throws Exception { | ||||
| 		this.context.register(CustomConfiguration.class, | ||||
| 				DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class, | ||||
| 				PropertyPlaceholderAutoConfiguration.class); | ||||
| 		this.context.refresh(); | ||||
| 		assertThat(this.context.getBean(JdbcOperations.class)) | ||||
| 				.isEqualTo(this.context.getBean("customJdbcOperations")); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testExistingCustomNamedParameterJdbcTemplate() throws Exception { | ||||
| 		this.context.register(CustomConfiguration.class, | ||||
| 				DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class, | ||||
| 				PropertyPlaceholderAutoConfiguration.class); | ||||
| 		this.context.refresh(); | ||||
| 		assertThat(this.context.getBean(NamedParameterJdbcOperations.class)) | ||||
| 				.isEqualTo(this.context.getBean("customNamedParameterJdbcOperations")); | ||||
| 	} | ||||
| 
 | ||||
| 	@Configuration | ||||
| 	static class CustomConfiguration { | ||||
| 
 | ||||
| 		@Bean | ||||
| 		public JdbcOperations customJdbcOperations(DataSource dataSource) { | ||||
| 			return new JdbcTemplate(dataSource); | ||||
| 		} | ||||
| 
 | ||||
| 		@Bean | ||||
| 		public NamedParameterJdbcOperations customNamedParameterJdbcOperations( | ||||
| 				DataSource dataSource) { | ||||
| 			return new NamedParameterJdbcTemplate(dataSource); | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	@Configuration | ||||
| 	static class TestDataSourceConfiguration { | ||||
| 
 | ||||
| 		@Bean | ||||
| 		public DataSource dataSource() { | ||||
| 			return new TestDataSource("overridedb"); | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
		Loading…
	
		Reference in New Issue