DevTools should only shut down single, auto-configured DataSource
Previously, there were two problems with DevTools’ DataSource auto-configuration: 1. It did not tolerate a context with multiple DataSources 2. It would attempt to shut down a DataSource that had not been created by DataSourceAutoConfiguration and, therefore, where we could not be sure of its configuration. This commit updates DevToolsDataSourceAutoConfiguration so that it backs off unless the context contains DataSourceProperties and a single DataSource created by DataSourceAutoConfiguration. This ensures that it can safely use DataSourceProperties to get the DataSource’s driver class name and accurately determine if it’s an in-memory or external database. Shutdown is only called for an in-memory database. Closes gh-5540
This commit is contained in:
@@ -23,18 +23,24 @@ import java.util.Set;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.AllNestedConditions;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.autoconfigure.data.jpa.EntityManagerFactoryDependsOnPostProcessor;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||
import org.springframework.boot.devtools.autoconfigure.DevToolsDataSourceAutoConfiguration.DevToolsDataSourceCondition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ConfigurationCondition;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
|
||||
import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
@@ -109,20 +115,37 @@ public class DevToolsDataSourceAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
static class DevToolsDataSourceCondition extends AllNestedConditions {
|
||||
static class DevToolsDataSourceCondition extends SpringBootCondition
|
||||
implements ConfigurationCondition {
|
||||
|
||||
DevToolsDataSourceCondition() {
|
||||
super(ConfigurationPhase.REGISTER_BEAN);
|
||||
@Override
|
||||
public ConfigurationPhase getConfigurationPhase() {
|
||||
return ConfigurationPhase.REGISTER_BEAN;
|
||||
}
|
||||
|
||||
@ConditionalOnBean(DataSource.class)
|
||||
static final class DataSourceBean {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnBean(DataSourceProperties.class)
|
||||
static final class DataSourcePropertiesBean {
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
String[] dataSourceBeanNames = context.getBeanFactory()
|
||||
.getBeanNamesForType(DataSource.class);
|
||||
if (dataSourceBeanNames.length != 1) {
|
||||
return ConditionOutcome
|
||||
.noMatch("A single DataSource bean was not found in the context");
|
||||
}
|
||||
if (context.getBeanFactory()
|
||||
.getBeanNamesForType(DataSourceProperties.class).length != 1) {
|
||||
return ConditionOutcome.noMatch(
|
||||
"A single DataSourceProperties bean was not found in the context");
|
||||
}
|
||||
BeanDefinition dataSourceDefinition = context.getRegistry()
|
||||
.getBeanDefinition(dataSourceBeanNames[0]);
|
||||
if (dataSourceDefinition instanceof AnnotatedBeanDefinition
|
||||
&& ((AnnotatedBeanDefinition) dataSourceDefinition)
|
||||
.getFactoryMethodMetadata().getDeclaringClassName()
|
||||
.startsWith(DataSourceAutoConfiguration.class.getName())) {
|
||||
return ConditionOutcome.match("Found auto-configured DataSource");
|
||||
}
|
||||
return ConditionOutcome.noMatch("DataSource was not auto-configured");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user