Commit 9b65409e authored by Andy Wilkinson's avatar Andy Wilkinson

Generalize database initialization detection and include R2DBC

Closes gh-25818
parent 22b02a6c
...@@ -50,7 +50,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties ...@@ -50,7 +50,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.jdbc.init.dependency.DataSourceInitializationDependencyConfigurer; import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -88,7 +88,7 @@ import org.springframework.util.StringUtils; ...@@ -88,7 +88,7 @@ import org.springframework.util.StringUtils;
@ConditionalOnProperty(prefix = "spring.flyway", name = "enabled", matchIfMissing = true) @ConditionalOnProperty(prefix = "spring.flyway", name = "enabled", matchIfMissing = true)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class, @AutoConfigureAfter({ DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
HibernateJpaAutoConfiguration.class }) HibernateJpaAutoConfiguration.class })
@Import(DataSourceInitializationDependencyConfigurer.class) @Import(DatabaseInitializationDependencyConfigurer.class)
public class FlywayAutoConfiguration { public class FlywayAutoConfiguration {
@Bean @Bean
......
...@@ -19,18 +19,18 @@ package org.springframework.boot.autoconfigure.flyway; ...@@ -19,18 +19,18 @@ package org.springframework.boot.autoconfigure.flyway;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import org.springframework.boot.jdbc.init.dependency.AbstractBeansOfTypeDataSourceInitializerDetector; import org.springframework.boot.sql.init.dependency.AbstractBeansOfTypeDatabaseInitializerDetector;
import org.springframework.boot.jdbc.init.dependency.DataSourceInitializerDetector; import org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector;
/** /**
* A {@link DataSourceInitializerDetector} for {@link FlywayMigrationInitializer}. * A {@link DatabaseInitializerDetector} for {@link FlywayMigrationInitializer}.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
class FlywayMigrationInitializerDataSourceInitializerDetector extends AbstractBeansOfTypeDataSourceInitializerDetector { class FlywayMigrationInitializerDatabaseInitializerDetector extends AbstractBeansOfTypeDatabaseInitializerDetector {
@Override @Override
protected Set<Class<?>> getDataSourceInitializerBeanTypes() { protected Set<Class<?>> getDatabaseInitializerBeanTypes() {
return Collections.singleton(FlywayMigrationInitializer.class); return Collections.singleton(FlywayMigrationInitializer.class);
} }
......
...@@ -42,8 +42,8 @@ import org.springframework.boot.jdbc.DataSourceBuilder; ...@@ -42,8 +42,8 @@ import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.DataSourceInitializationMode; import org.springframework.boot.jdbc.DataSourceInitializationMode;
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection; import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer; import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
import org.springframework.boot.jdbc.init.dependency.DataSourceInitializationDependencyConfigurer;
import org.springframework.boot.sql.init.DatabaseInitializationSettings; import org.springframework.boot.sql.init.DatabaseInitializationSettings;
import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.DependsOn;
...@@ -85,7 +85,7 @@ class DataSourceInitializationConfiguration { ...@@ -85,7 +85,7 @@ class DataSourceInitializationConfiguration {
// Fully-qualified to work around javac bug in JDK 1.8 // Fully-qualified to work around javac bug in JDK 1.8
@org.springframework.context.annotation.Configuration(proxyBeanMethods = false) @org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
@org.springframework.context.annotation.Conditional(DifferentCredentialsCondition.class) @org.springframework.context.annotation.Conditional(DifferentCredentialsCondition.class)
@org.springframework.context.annotation.Import(DataSourceInitializationDependencyConfigurer.class) @org.springframework.context.annotation.Import(DatabaseInitializationDependencyConfigurer.class)
@ConditionalOnSingleCandidate(DataSource.class) @ConditionalOnSingleCandidate(DataSource.class)
@ConditionalOnMissingBean(DataSourceScriptDatabaseInitializer.class) @ConditionalOnMissingBean(DataSourceScriptDatabaseInitializer.class)
static class InitializationSpecificCredentialsDataSourceInitializationConfiguration { static class InitializationSpecificCredentialsDataSourceInitializationConfiguration {
...@@ -141,7 +141,7 @@ class DataSourceInitializationConfiguration { ...@@ -141,7 +141,7 @@ class DataSourceInitializationConfiguration {
// Fully-qualified to work around javac bug in JDK 1.8 // Fully-qualified to work around javac bug in JDK 1.8
@org.springframework.context.annotation.Configuration(proxyBeanMethods = false) @org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
@org.springframework.context.annotation.Import(DataSourceInitializationDependencyConfigurer.class) @org.springframework.context.annotation.Import(DatabaseInitializationDependencyConfigurer.class)
@org.springframework.context.annotation.Conditional(DataSourceInitializationCondition.class) @org.springframework.context.annotation.Conditional(DataSourceInitializationCondition.class)
@ConditionalOnSingleCandidate(DataSource.class) @ConditionalOnSingleCandidate(DataSource.class)
@ConditionalOnMissingBean(DataSourceScriptDatabaseInitializer.class) @ConditionalOnMissingBean(DataSourceScriptDatabaseInitializer.class)
......
...@@ -19,7 +19,7 @@ package org.springframework.boot.autoconfigure.jdbc; ...@@ -19,7 +19,7 @@ package org.springframework.boot.autoconfigure.jdbc;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.AbstractDependsOnBeanFactoryPostProcessor; import org.springframework.boot.autoconfigure.AbstractDependsOnBeanFactoryPostProcessor;
import org.springframework.boot.jdbc.init.dependency.DependsOnDataSourceInitializationDetector; import org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector;
import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.JdbcOperations;
/** /**
...@@ -33,7 +33,7 @@ import org.springframework.jdbc.core.JdbcOperations; ...@@ -33,7 +33,7 @@ import org.springframework.jdbc.core.JdbcOperations;
* @author Andrii Hrytsiuk * @author Andrii Hrytsiuk
* @since 2.0.4 * @since 2.0.4
* @see BeanDefinition#setDependsOn(String[]) * @see BeanDefinition#setDependsOn(String[])
* @deprecated since 2.5.0 in favor of {@link DependsOnDataSourceInitializationDetector} * @deprecated since 2.5.0 in favor of {@link DependsOnDatabaseInitializationDetector}
*/ */
@Deprecated @Deprecated
public class JdbcOperationsDependsOnPostProcessor extends AbstractDependsOnBeanFactoryPostProcessor { public class JdbcOperationsDependsOnPostProcessor extends AbstractDependsOnBeanFactoryPostProcessor {
......
...@@ -23,7 +23,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; ...@@ -23,7 +23,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.init.dependency.DataSourceInitializationDependencyConfigurer; import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
...@@ -44,7 +44,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; ...@@ -44,7 +44,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
@ConditionalOnSingleCandidate(DataSource.class) @ConditionalOnSingleCandidate(DataSource.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class) @AutoConfigureAfter(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(JdbcProperties.class) @EnableConfigurationProperties(JdbcProperties.class)
@Import({ DataSourceInitializationDependencyConfigurer.class, JdbcTemplateConfiguration.class, @Import({ DatabaseInitializationDependencyConfigurer.class, JdbcTemplateConfiguration.class,
NamedParameterJdbcTemplateConfiguration.class }) NamedParameterJdbcTemplateConfiguration.class })
public class JdbcTemplateAutoConfiguration { public class JdbcTemplateAutoConfiguration {
......
...@@ -19,7 +19,7 @@ package org.springframework.boot.autoconfigure.jdbc; ...@@ -19,7 +19,7 @@ package org.springframework.boot.autoconfigure.jdbc;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.AbstractDependsOnBeanFactoryPostProcessor; import org.springframework.boot.autoconfigure.AbstractDependsOnBeanFactoryPostProcessor;
import org.springframework.boot.jdbc.init.dependency.DependsOnDataSourceInitializationDetector; import org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
/** /**
...@@ -31,7 +31,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; ...@@ -31,7 +31,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
* @author Andrii Hrytsiuk * @author Andrii Hrytsiuk
* @since 2.1.4 * @since 2.1.4
* @see BeanDefinition#setDependsOn(String[]) * @see BeanDefinition#setDependsOn(String[])
* @deprecated since 2.5.0 in favor of {@link DependsOnDataSourceInitializationDetector} * @deprecated since 2.5.0 in favor of {@link DependsOnDatabaseInitializationDetector}
*/ */
@Deprecated @Deprecated
public class NamedParameterJdbcOperationsDependsOnPostProcessor extends AbstractDependsOnBeanFactoryPostProcessor { public class NamedParameterJdbcOperationsDependsOnPostProcessor extends AbstractDependsOnBeanFactoryPostProcessor {
......
...@@ -21,7 +21,7 @@ import org.jooq.DSLContext; ...@@ -21,7 +21,7 @@ import org.jooq.DSLContext;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.AbstractDependsOnBeanFactoryPostProcessor; import org.springframework.boot.autoconfigure.AbstractDependsOnBeanFactoryPostProcessor;
import org.springframework.boot.jdbc.init.dependency.DependsOnDataSourceInitializationDetector; import org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector;
/** /**
* {@link BeanFactoryPostProcessor} that can be used to dynamically declare that all * {@link BeanFactoryPostProcessor} that can be used to dynamically declare that all
...@@ -30,7 +30,7 @@ import org.springframework.boot.jdbc.init.dependency.DependsOnDataSourceInitiali ...@@ -30,7 +30,7 @@ import org.springframework.boot.jdbc.init.dependency.DependsOnDataSourceInitiali
* @author Eddú Meléndez * @author Eddú Meléndez
* @since 2.3.9 * @since 2.3.9
* @see BeanDefinition#setDependsOn(String[]) * @see BeanDefinition#setDependsOn(String[])
* @deprecated since 2.5.0 in favor of {@link DependsOnDataSourceInitializationDetector} * @deprecated since 2.5.0 in favor of {@link DependsOnDatabaseInitializationDetector}
*/ */
@Deprecated @Deprecated
public class DslContextDependsOnPostProcessor extends AbstractDependsOnBeanFactoryPostProcessor { public class DslContextDependsOnPostProcessor extends AbstractDependsOnBeanFactoryPostProcessor {
......
...@@ -34,7 +34,7 @@ import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfigurati ...@@ -34,7 +34,7 @@ import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfigurati
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.init.dependency.DataSourceInitializationDependencyConfigurer; import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -63,7 +63,7 @@ import org.springframework.util.StringUtils; ...@@ -63,7 +63,7 @@ import org.springframework.util.StringUtils;
@ConditionalOnProperty(prefix = "spring.liquibase", name = "enabled", matchIfMissing = true) @ConditionalOnProperty(prefix = "spring.liquibase", name = "enabled", matchIfMissing = true)
@Conditional(LiquibaseDataSourceCondition.class) @Conditional(LiquibaseDataSourceCondition.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class }) @AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
@Import(DataSourceInitializationDependencyConfigurer.class) @Import(DatabaseInitializationDependencyConfigurer.class)
public class LiquibaseAutoConfiguration { public class LiquibaseAutoConfiguration {
@Bean @Bean
......
...@@ -22,19 +22,16 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean ...@@ -22,19 +22,16 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer; import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
import org.springframework.boot.jdbc.init.dependency.DataSourceInitializationDependencyConfigurer;
import org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer; import org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer;
import org.springframework.boot.sql.init.DatabaseInitializationSettings; import org.springframework.boot.sql.init.DatabaseInitializationSettings;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.datasource.SimpleDriverDataSource; import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(AbstractScriptDatabaseInitializer.class) @ConditionalOnMissingBean(AbstractScriptDatabaseInitializer.class)
@ConditionalOnSingleCandidate(DataSource.class) @ConditionalOnSingleCandidate(DataSource.class)
@Import(DataSourceInitializationDependencyConfigurer.class)
class DataSourceInitializationConfiguration { class DataSourceInitializationConfiguration {
@Bean @Bean
......
...@@ -24,6 +24,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; ...@@ -24,6 +24,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration; import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer; import org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer;
import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
...@@ -38,7 +39,8 @@ import org.springframework.context.annotation.Import; ...@@ -38,7 +39,8 @@ import org.springframework.context.annotation.Import;
@ConditionalOnProperty(prefix = "spring.sql.init", name = "enabled", matchIfMissing = true) @ConditionalOnProperty(prefix = "spring.sql.init", name = "enabled", matchIfMissing = true)
@AutoConfigureAfter({ R2dbcAutoConfiguration.class, DataSourceAutoConfiguration.class }) @AutoConfigureAfter({ R2dbcAutoConfiguration.class, DataSourceAutoConfiguration.class })
@EnableConfigurationProperties(SqlInitializationProperties.class) @EnableConfigurationProperties(SqlInitializationProperties.class)
@Import({ R2dbcInitializationConfiguration.class, DataSourceInitializationConfiguration.class }) @Import({ DatabaseInitializationDependencyConfigurer.class, R2dbcInitializationConfiguration.class,
DataSourceInitializationConfiguration.class })
public class SqlInitializationAutoConfiguration { public class SqlInitializationAutoConfiguration {
} }
...@@ -173,5 +173,5 @@ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityPr ...@@ -173,5 +173,5 @@ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityPr
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
# DataSource initializer detectors # DataSource initializer detectors
org.springframework.boot.jdbc.init.dependency.DataSourceInitializerDetector=\ org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector=\
org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializerDataSourceInitializerDetector org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializerDatabaseInitializerDetector
...@@ -44,7 +44,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations; ...@@ -44,7 +44,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection; import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer; import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
import org.springframework.boot.jdbc.init.dependency.DependsOnDataSourceInitialization; import org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitialization;
import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
...@@ -283,7 +283,7 @@ class DataSourceAutoConfigurationTests { ...@@ -283,7 +283,7 @@ class DataSourceAutoConfigurationTests {
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@DependsOnDataSourceInitialization @DependsOnDatabaseInitialization
static class TestInitializedDataSourceConfiguration { static class TestInitializedDataSourceConfiguration {
private boolean called; private boolean called;
......
...@@ -59,10 +59,10 @@ import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfigurat ...@@ -59,10 +59,10 @@ import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfigurat
import org.springframework.boot.autoconfigure.orm.jpa.mapping.NonAnnotatedEntity; import org.springframework.boot.autoconfigure.orm.jpa.mapping.NonAnnotatedEntity;
import org.springframework.boot.autoconfigure.orm.jpa.test.City; import org.springframework.boot.autoconfigure.orm.jpa.test.City;
import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration; import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration;
import org.springframework.boot.jdbc.init.dependency.DependsOnDataSourceInitialization;
import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy; import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy;
import org.springframework.boot.orm.jpa.hibernate.SpringJtaPlatform; import org.springframework.boot.orm.jpa.hibernate.SpringJtaPlatform;
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
import org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitialization;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.boot.test.context.runner.ContextConsumer;
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEvent;
...@@ -501,7 +501,7 @@ class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTes ...@@ -501,7 +501,7 @@ class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTes
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(City.class) @TestAutoConfigurationPackage(City.class)
@DependsOnDataSourceInitialization @DependsOnDatabaseInitialization
static class TestInitializedJpaConfiguration { static class TestInitializedJpaConfiguration {
private boolean called; private boolean called;
......
...@@ -24,6 +24,7 @@ import javax.sql.DataSource; ...@@ -24,6 +24,7 @@ import javax.sql.DataSource;
import io.r2dbc.spi.ConnectionFactory; import io.r2dbc.spi.ConnectionFactory;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration; import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration;
...@@ -31,6 +32,7 @@ import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer; ...@@ -31,6 +32,7 @@ import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
import org.springframework.boot.r2dbc.init.R2dbcScriptDatabaseInitializer; import org.springframework.boot.r2dbc.init.R2dbcScriptDatabaseInitializer;
import org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer; import org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer;
import org.springframework.boot.sql.init.DatabaseInitializationSettings; import org.springframework.boot.sql.init.DatabaseInitializationSettings;
import org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitialization;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -98,6 +100,28 @@ public class SqlInitializationAutoConfigurationTests { ...@@ -98,6 +100,28 @@ public class SqlInitializationAutoConfigurationTests {
.hasBean("customInitializer")); .hasBean("customInitializer"));
} }
@Test
void whenBeanIsAnnotatedAsDependingOnDatabaseInitializationThenItDependsOnR2dbcScriptDatabaseInitializer() {
this.contextRunner.withConfiguration(AutoConfigurations.of(R2dbcAutoConfiguration.class))
.withUserConfiguration(DependsOnInitializedDatabaseConfiguration.class).run((context) -> {
BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition(
"sqlInitializationAutoConfigurationTests.DependsOnInitializedDatabaseConfiguration");
assertThat(beanDefinition.getDependsOn())
.containsExactlyInAnyOrder("r2dbcScriptDatabaseInitializer");
});
}
@Test
void whenBeanIsAnnotatedAsDependingOnDatabaseInitializationThenItDependsOnDataSourceScriptDatabaseInitializer() {
this.contextRunner.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
.withUserConfiguration(DependsOnInitializedDatabaseConfiguration.class).run((context) -> {
BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition(
"sqlInitializationAutoConfigurationTests.DependsOnInitializedDatabaseConfiguration");
assertThat(beanDefinition.getDependsOn())
.containsExactlyInAnyOrder("dataSourceScriptDatabaseInitializer");
});
}
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
static class DatabaseInitializerConfiguration { static class DatabaseInitializerConfiguration {
...@@ -116,4 +140,14 @@ public class SqlInitializationAutoConfigurationTests { ...@@ -116,4 +140,14 @@ public class SqlInitializationAutoConfigurationTests {
} }
@Configuration(proxyBeanMethods = false)
@DependsOnDatabaseInitialization
static class DependsOnInitializedDatabaseConfiguration {
DependsOnInitializedDatabaseConfiguration() {
}
}
} }
...@@ -2163,33 +2163,33 @@ See {spring-boot-autoconfigure-module-code}/liquibase/LiquibaseProperties.java[` ...@@ -2163,33 +2163,33 @@ See {spring-boot-autoconfigure-module-code}/liquibase/LiquibaseProperties.java[`
[[howto-initialize-a-database-configuring-dependencies]] [[howto-initialize-a-database-configuring-dependencies]]
=== Depend Upon an Initialized DataSource === Depend Upon an Initialized Database
DataSource initialization is performed while the application is starting up as part of application context refresh. Database initialization is performed while the application is starting up as part of application context refresh.
To allow an initialized database to be accessed during startup, beans that act as DataSource initializers and beans that To allow an initialized database to be accessed during startup, beans that act as database initializers and beans that require that database to have been initialized are detected automatically.
require that DataSource to have been initialized are detected automatically. Beans whose initialization depends upon the database having been initialized are configured to depend upon those that initialize it.
Beans whose initialization depends upon the DataSource having been initialized are configured to depend upon those that initialize it. If, during startup, your application tries to access the database and it has not been initialized, you can configure additional detection of beans that initialize the database and require the database to have been initialized.
If, during startup, your application tries to access the database and it has not been initialized, you can configure additional detection of beans that initialize the DataSource and require the DataSource to have been initialized.
[[howto-initialize-a-database-configuring-dependencies-initializer-detection]] [[howto-initialize-a-database-configuring-dependencies-initializer-detection]]
==== Detect a DataSource Initializer ==== Detect a Database Initializer
Spring Boot will automatically detect beans of the following types that initialize a `DataSource`: Spring Boot will automatically detect beans of the following types that initialize an SQL database:
- `DataSourceInitialization` - `DataSourceScriptDatabaseInitializer`
- `EntityManagerFactory` - `EntityManagerFactory`
- `Flyway` - `Flyway`
- `FlywayMigrationInitializer` - `FlywayMigrationInitializer`
- `R2dbcScriptDatabaseInitializer`
- `SpringLiquibase` - `SpringLiquibase`
If you are using a third-party starter for a DataSource initialization library, it may provide a detector such that beans of other types are also detected automatically. If you are using a third-party starter for a database initialization library, it may provide a detector such that beans of other types are also detected automatically.
To have other beans be detected, register an implementation of `DataSourceInitializerDetector` in `META-INF/spring-factories`. To have other beans be detected, register an implementation of `DatabaseInitializerDetector` in `META-INF/spring-factories`.
[[howto-initialize-a-database-configuring-dependencies-depends-on-initialization-detection]] [[howto-initialize-a-database-configuring-dependencies-depends-on-initialization-detection]]
==== Detect a Bean That Depends On DataSource Initialization ==== Detect a Bean That Depends On Database Initialization
Spring Boot will automatically detect beans of the following types that depends upon `DataSource` initialization: Spring Boot will automatically detect beans of the following types that depends upon database initialization:
- `AbstractEntityManagerFactoryBean` (unless configprop:spring.jpa.defer-datasource-initialization[] is set to `true`) - `AbstractEntityManagerFactoryBean` (unless configprop:spring.jpa.defer-datasource-initialization[] is set to `true`)
- `DSLContext` (jOOQ) - `DSLContext` (jOOQ)
...@@ -2198,8 +2198,8 @@ Spring Boot will automatically detect beans of the following types that depends ...@@ -2198,8 +2198,8 @@ Spring Boot will automatically detect beans of the following types that depends
- `NamedParameterJdbcOperations` - `NamedParameterJdbcOperations`
If you are using a third-party starter data access library, it may provide a detector such that beans of other types are also detected automatically. If you are using a third-party starter data access library, it may provide a detector such that beans of other types are also detected automatically.
To have other beans be detected, register an implementation of `DependsOnDataSourceInitializationDetector` in `META-INF/spring-factories`. To have other beans be detected, register an implementation of `DependsOnDatabaseInitializationDetector` in `META-INF/spring-factories`.
Alternatively, annotate the bean's class or its `@Bean` method with `@DependsOnDataSourceInitializationDetector`. Alternatively, annotate the bean's class or its `@Bean` method with `@DependsOnDatabaseInitialization`.
......
...@@ -21,18 +21,18 @@ import java.util.Set; ...@@ -21,18 +21,18 @@ import java.util.Set;
import org.flywaydb.core.Flyway; import org.flywaydb.core.Flyway;
import org.springframework.boot.jdbc.init.dependency.AbstractBeansOfTypeDataSourceInitializerDetector; import org.springframework.boot.sql.init.dependency.AbstractBeansOfTypeDatabaseInitializerDetector;
import org.springframework.boot.jdbc.init.dependency.DataSourceInitializerDetector; import org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector;
/** /**
* A {@link DataSourceInitializerDetector} for {@link Flyway}. * A {@link DatabaseInitializerDetector} for {@link Flyway}.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
class FlywayDataSourceInitializerDetector extends AbstractBeansOfTypeDataSourceInitializerDetector { class FlywayDatabaseInitializerDetector extends AbstractBeansOfTypeDatabaseInitializerDetector {
@Override @Override
protected Set<Class<?>> getDataSourceInitializerBeanTypes() { protected Set<Class<?>> getDatabaseInitializerBeanTypes() {
return Collections.singleton(Flyway.class); return Collections.singleton(Flyway.class);
} }
......
...@@ -20,21 +20,21 @@ import java.util.Arrays; ...@@ -20,21 +20,21 @@ import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.springframework.boot.jdbc.init.dependency.AbstractBeansOfTypeDependsOnDataSourceInitializationDetector; import org.springframework.boot.sql.init.dependency.AbstractBeansOfTypeDependsOnDatabaseInitializationDetector;
import org.springframework.boot.jdbc.init.dependency.DependsOnDataSourceInitializationDetector; import org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector;
import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
/** /**
* {@link DependsOnDataSourceInitializationDetector} for Spring Framework's JDBC support. * {@link DependsOnDatabaseInitializationDetector} for Spring Framework's JDBC support.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
class SpringJdbcDependsOnDataSourceInitializationDetector class SpringJdbcDependsOnDatabaseInitializationDetector
extends AbstractBeansOfTypeDependsOnDataSourceInitializationDetector { extends AbstractBeansOfTypeDependsOnDatabaseInitializationDetector {
@Override @Override
protected Set<Class<?>> getDependsOnDataSourceInitializationBeanTypes() { protected Set<Class<?>> getDependsOnDatabaseInitializationBeanTypes() {
return new HashSet<>(Arrays.asList(JdbcOperations.class, NamedParameterJdbcOperations.class)); return new HashSet<>(Arrays.asList(JdbcOperations.class, NamedParameterJdbcOperations.class));
} }
......
...@@ -19,19 +19,18 @@ package org.springframework.boot.jdbc.init; ...@@ -19,19 +19,18 @@ package org.springframework.boot.jdbc.init;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import org.springframework.boot.jdbc.init.dependency.AbstractBeansOfTypeDataSourceInitializerDetector; import org.springframework.boot.sql.init.dependency.AbstractBeansOfTypeDatabaseInitializerDetector;
import org.springframework.boot.jdbc.init.dependency.DataSourceInitializerDetector; import org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector;
/** /**
* A {@link DataSourceInitializerDetector} for * A {@link DatabaseInitializerDetector} for {@link DataSourceScriptDatabaseInitializer}.
* {@link DataSourceScriptDatabaseInitializer}.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
class DataSourceScriptDatabaseInitializerDetector extends AbstractBeansOfTypeDataSourceInitializerDetector { class DataSourceScriptDatabaseInitializerDetector extends AbstractBeansOfTypeDatabaseInitializerDetector {
@Override @Override
protected Set<Class<?>> getDataSourceInitializerBeanTypes() { protected Set<Class<?>> getDatabaseInitializerBeanTypes() {
return Collections.singleton(DataSourceScriptDatabaseInitializer.class); return Collections.singleton(DataSourceScriptDatabaseInitializer.class);
} }
......
...@@ -21,19 +21,18 @@ import java.util.Set; ...@@ -21,19 +21,18 @@ import java.util.Set;
import org.jooq.DSLContext; import org.jooq.DSLContext;
import org.springframework.boot.jdbc.init.dependency.AbstractBeansOfTypeDependsOnDataSourceInitializationDetector; import org.springframework.boot.sql.init.dependency.AbstractBeansOfTypeDependsOnDatabaseInitializationDetector;
import org.springframework.boot.jdbc.init.dependency.DependsOnDataSourceInitializationDetector; import org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector;
/** /**
* {@link DependsOnDataSourceInitializationDetector} for jOOQ. * {@link DependsOnDatabaseInitializationDetector} for jOOQ.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
class JooqDependsOnDataSourceInitializationDetector class JooqDependsOnDatabaseInitializationDetector extends AbstractBeansOfTypeDependsOnDatabaseInitializationDetector {
extends AbstractBeansOfTypeDependsOnDataSourceInitializationDetector {
@Override @Override
protected Set<Class<?>> getDependsOnDataSourceInitializationBeanTypes() { protected Set<Class<?>> getDependsOnDatabaseInitializationBeanTypes() {
return Collections.singleton(DSLContext.class); return Collections.singleton(DSLContext.class);
} }
......
...@@ -21,18 +21,18 @@ import java.util.Set; ...@@ -21,18 +21,18 @@ import java.util.Set;
import liquibase.integration.spring.SpringLiquibase; import liquibase.integration.spring.SpringLiquibase;
import org.springframework.boot.jdbc.init.dependency.AbstractBeansOfTypeDataSourceInitializerDetector; import org.springframework.boot.sql.init.dependency.AbstractBeansOfTypeDatabaseInitializerDetector;
import org.springframework.boot.jdbc.init.dependency.DataSourceInitializerDetector; import org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector;
/** /**
* A {@link DataSourceInitializerDetector} for Liquibase. * A {@link DatabaseInitializerDetector} for Liquibase.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
class LiquibaseDataSourceInitializerDetector extends AbstractBeansOfTypeDataSourceInitializerDetector { class LiquibaseDatabaseInitializerDetector extends AbstractBeansOfTypeDatabaseInitializerDetector {
@Override @Override
protected Set<Class<?>> getDataSourceInitializerBeanTypes() { protected Set<Class<?>> getDatabaseInitializerBeanTypes() {
return Collections.singleton(SpringLiquibase.class); return Collections.singleton(SpringLiquibase.class);
} }
......
...@@ -25,26 +25,26 @@ import javax.persistence.EntityManagerFactory; ...@@ -25,26 +25,26 @@ import javax.persistence.EntityManagerFactory;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.jdbc.init.dependency.AbstractBeansOfTypeDataSourceInitializerDetector; import org.springframework.boot.sql.init.dependency.AbstractBeansOfTypeDatabaseInitializerDetector;
import org.springframework.boot.jdbc.init.dependency.DataSourceInitializerDetector; import org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
* A {@link DataSourceInitializerDetector} for JPA. * A {@link DatabaseInitializerDetector} for JPA.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
class JpaDataSourceInitializerDetector extends AbstractBeansOfTypeDataSourceInitializerDetector { class JpaDatabaseInitializerDetector extends AbstractBeansOfTypeDatabaseInitializerDetector {
private final Environment environment; private final Environment environment;
JpaDataSourceInitializerDetector(Environment environment) { JpaDatabaseInitializerDetector(Environment environment) {
this.environment = environment; this.environment = environment;
} }
@Override @Override
protected Set<Class<?>> getDataSourceInitializerBeanTypes() { protected Set<Class<?>> getDatabaseInitializerBeanTypes() {
boolean deferred = this.environment.getProperty("spring.jpa.defer-datasource-initialization", boolean.class, boolean deferred = this.environment.getProperty("spring.jpa.defer-datasource-initialization", boolean.class,
false); false);
return deferred ? Collections.singleton(EntityManagerFactory.class) : Collections.emptySet(); return deferred ? Collections.singleton(EntityManagerFactory.class) : Collections.emptySet();
...@@ -63,8 +63,8 @@ class JpaDataSourceInitializerDetector extends AbstractBeansOfTypeDataSourceInit ...@@ -63,8 +63,8 @@ class JpaDataSourceInitializerDetector extends AbstractBeansOfTypeDataSourceInit
while (iterator.hasNext()) { while (iterator.hasNext()) {
String initializerName = iterator.next(); String initializerName = iterator.next();
BeanDefinition initializerDefinition = beanFactory.getBeanDefinition(initializerName); BeanDefinition initializerDefinition = beanFactory.getBeanDefinition(initializerName);
if (JpaDataSourceInitializerDetector.class.getName() if (JpaDatabaseInitializerDetector.class.getName()
.equals(initializerDefinition.getAttribute(DataSourceInitializerDetector.class.getName()))) { .equals(initializerDefinition.getAttribute(DatabaseInitializerDetector.class.getName()))) {
iterator.remove(); iterator.remove();
jpaInitializers.add(initializerName); jpaInitializers.add(initializerName);
} }
......
...@@ -23,27 +23,26 @@ import java.util.Set; ...@@ -23,27 +23,26 @@ import java.util.Set;
import javax.persistence.EntityManagerFactory; import javax.persistence.EntityManagerFactory;
import org.springframework.boot.jdbc.init.dependency.AbstractBeansOfTypeDependsOnDataSourceInitializationDetector; import org.springframework.boot.sql.init.dependency.AbstractBeansOfTypeDependsOnDatabaseInitializationDetector;
import org.springframework.boot.jdbc.init.dependency.DependsOnDataSourceInitializationDetector; import org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean; import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean;
/** /**
* {@link DependsOnDataSourceInitializationDetector} for JPA. * {@link DependsOnDatabaseInitializationDetector} for JPA.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
class JpaDependsOnDataSourceInitializationDetector class JpaDependsOnDatabaseInitializationDetector extends AbstractBeansOfTypeDependsOnDatabaseInitializationDetector {
extends AbstractBeansOfTypeDependsOnDataSourceInitializationDetector {
private final Environment environment; private final Environment environment;
JpaDependsOnDataSourceInitializationDetector(Environment environment) { JpaDependsOnDatabaseInitializationDetector(Environment environment) {
this.environment = environment; this.environment = environment;
} }
@Override @Override
protected Set<Class<?>> getDependsOnDataSourceInitializationBeanTypes() { protected Set<Class<?>> getDependsOnDatabaseInitializationBeanTypes() {
boolean postpone = this.environment.getProperty("spring.jpa.defer-datasource-initialization", boolean.class, boolean postpone = this.environment.getProperty("spring.jpa.defer-datasource-initialization", boolean.class,
false); false);
return postpone ? Collections.emptySet() return postpone ? Collections.emptySet()
......
/*
* Copyright 2012-2021 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
*
* https://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.r2dbc.init;
import java.util.Collections;
import java.util.Set;
import org.springframework.boot.sql.init.dependency.AbstractBeansOfTypeDatabaseInitializerDetector;
import org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector;
/**
* A {@link DatabaseInitializerDetector} for {@link R2dbcScriptDatabaseInitializer}.
*
* @author Andy Wilkinson
*/
class R2dbcScriptDatabaseInitializerDetector extends AbstractBeansOfTypeDatabaseInitializerDetector {
@Override
protected Set<Class<?>> getDatabaseInitializerBeanTypes() {
return Collections.singleton(R2dbcScriptDatabaseInitializer.class);
}
}
...@@ -14,34 +14,32 @@ ...@@ -14,34 +14,32 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.jdbc.init.dependency; package org.springframework.boot.sql.init.dependency;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import javax.sql.DataSource;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
/** /**
* Base class for {@link DataSourceInitializerDetector DataSourceInitializerDetectors} * Base class for {@link DatabaseInitializerDetector DatabaseInitializerDetectors} that
* that detect {@link DataSource} beans by type. * detect database initializer beans by type.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 2.5.0 * @since 2.5.0
*/ */
public abstract class AbstractBeansOfTypeDataSourceInitializerDetector implements DataSourceInitializerDetector { public abstract class AbstractBeansOfTypeDatabaseInitializerDetector implements DatabaseInitializerDetector {
/** /**
* Returns the bean types that should be detected as being data source initializers. * Returns the bean types that should be detected as being database initializers.
* @return the data source initializer bean types * @return the database initializer bean types
*/ */
protected abstract Set<Class<?>> getDataSourceInitializerBeanTypes(); protected abstract Set<Class<?>> getDatabaseInitializerBeanTypes();
@Override @Override
public Set<String> detect(ConfigurableListableBeanFactory beanFactory) { public Set<String> detect(ConfigurableListableBeanFactory beanFactory) {
try { try {
Set<Class<?>> types = getDataSourceInitializerBeanTypes(); Set<Class<?>> types = getDatabaseInitializerBeanTypes();
return new BeansOfTypeDetector(types).detect(beanFactory); return new BeansOfTypeDetector(types).detect(beanFactory);
} }
catch (Throwable ex) { catch (Throwable ex) {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.jdbc.init.dependency; package org.springframework.boot.sql.init.dependency;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
...@@ -22,27 +22,27 @@ import java.util.Set; ...@@ -22,27 +22,27 @@ import java.util.Set;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
/** /**
* Base class for {@link DependsOnDataSourceInitializationDetector * Base class for {@link DependsOnDatabaseInitializationDetector
* InitializedDataSourceDependentDetector} that detect by type beans that depend upon data * DependsOnDatabaseInitializationDetectors} that detect by type beans that depend upon
* source initialization. * database initialization.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 2.5.0 * @since 2.5.0
*/ */
public abstract class AbstractBeansOfTypeDependsOnDataSourceInitializationDetector public abstract class AbstractBeansOfTypeDependsOnDatabaseInitializationDetector
implements DependsOnDataSourceInitializationDetector { implements DependsOnDatabaseInitializationDetector {
/** /**
* Returns the bean types that should be detected as depending on data source * Returns the bean types that should be detected as depending on database
* initialization. * initialization.
* @return the data source initialization dependent bean types * @return the database initialization dependent bean types
*/ */
protected abstract Set<Class<?>> getDependsOnDataSourceInitializationBeanTypes(); protected abstract Set<Class<?>> getDependsOnDatabaseInitializationBeanTypes();
@Override @Override
public Set<String> detect(ConfigurableListableBeanFactory beanFactory) { public Set<String> detect(ConfigurableListableBeanFactory beanFactory) {
try { try {
Set<Class<?>> types = getDependsOnDataSourceInitializationBeanTypes(); Set<Class<?>> types = getDependsOnDatabaseInitializationBeanTypes();
return new BeansOfTypeDetector(types).detect(beanFactory); return new BeansOfTypeDetector(types).detect(beanFactory);
} }
catch (Throwable ex) { catch (Throwable ex) {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.jdbc.init.dependency; package org.springframework.boot.sql.init.dependency;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
...@@ -22,18 +22,18 @@ import java.util.Set; ...@@ -22,18 +22,18 @@ import java.util.Set;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
/** /**
* {@link DependsOnDataSourceInitializationDetector} that detects beans annotated with * {@link DependsOnDatabaseInitializationDetector} that detects beans annotated with
* {@link DependsOnDataSourceInitialization}. * {@link DependsOnDatabaseInitialization}.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
class AnnotationDependsOnDataSourceInitializationDetector implements DependsOnDataSourceInitializationDetector { class AnnotationDependsOnDatabaseInitializationDetector implements DependsOnDatabaseInitializationDetector {
@Override @Override
public Set<String> detect(ConfigurableListableBeanFactory beanFactory) { public Set<String> detect(ConfigurableListableBeanFactory beanFactory) {
Set<String> dependentBeans = new HashSet<>(); Set<String> dependentBeans = new HashSet<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) { for (String beanName : beanFactory.getBeanDefinitionNames()) {
if (beanFactory.findAnnotationOnBean(beanName, DependsOnDataSourceInitialization.class) != null) { if (beanFactory.findAnnotationOnBean(beanName, DependsOnDatabaseInitialization.class) != null) {
dependentBeans.add(beanName); dependentBeans.add(beanName);
} }
} }
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.jdbc.init.dependency; package org.springframework.boot.sql.init.dependency;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.jdbc.init.dependency; package org.springframework.boot.sql.init.dependency;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
...@@ -22,8 +22,6 @@ import java.util.HashSet; ...@@ -22,8 +22,6 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.sql.DataSource;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
...@@ -40,93 +38,95 @@ import org.springframework.core.type.AnnotationMetadata; ...@@ -40,93 +38,95 @@ import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
* Configures beans that depend upon DataSource initialization with * Configures beans that depend upon SQL database initialization with
* {@link BeanDefinition#getDependsOn()} dependencies upon beans that perform * {@link BeanDefinition#getDependsOn() dependencies} upon beans that perform database
* {@link DataSource} initialization. Intended for {@link Import import} in configuration * initialization. Intended for {@link Import import} in configuration classes that define
* classes that define {@code DataSource} initialization beans or that define beans that * database initialization beans or that define beans that require database initialization
* require DataSource initialization to have completed before they are initialized. * to have completed before they are initialized.
* <p> * <p>
* Beans that initialize a {@link DataSource} are identified by * Beans that initialize a database are identified by {@link DatabaseInitializerDetector
* {@link DataSourceInitializerDetector DataSourceInitializerDetectors}. Beans that depend * DatabaseInitializerDetectors}. Beans that depend upon database initialization are
* upon DataSource initialization are identified by * identified by {@link DependsOnDatabaseInitializationDetector
* {@link DependsOnDataSourceInitializationDetector * DependsOnDatabaseInitializationDetectors}.
* DependsOnDataSourceInitializationDetectors}.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 2.5.0 * @since 2.5.0
* @see DataSourceInitializerDetector * @see DatabaseInitializerDetector
* @see DependsOnDataSourceInitializationDetector * @see DependsOnDatabaseInitializationDetector
* @see DependsOnDataSourceInitialization * @see DependsOnDatabaseInitialization
*/ */
public class DataSourceInitializationDependencyConfigurer implements ImportBeanDefinitionRegistrar { public class DatabaseInitializationDependencyConfigurer implements ImportBeanDefinitionRegistrar {
private final Environment environment; private final Environment environment;
DataSourceInitializationDependencyConfigurer(Environment environment) { DatabaseInitializationDependencyConfigurer(Environment environment) {
this.environment = environment; this.environment = environment;
} }
@Override @Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(DependsOnDataSourceInitializationPostProcessor.class.getName())) { if (registry.containsBeanDefinition(DependsOnDatabaseInitializationPostProcessor.class.getName())) {
return; return;
} }
registry.registerBeanDefinition(DependsOnDataSourceInitializationPostProcessor.class.getName(), registry.registerBeanDefinition(DependsOnDatabaseInitializationPostProcessor.class.getName(),
BeanDefinitionBuilder BeanDefinitionBuilder
.genericBeanDefinition(DependsOnDataSourceInitializationPostProcessor.class, .genericBeanDefinition(DependsOnDatabaseInitializationPostProcessor.class,
() -> new DependsOnDataSourceInitializationPostProcessor(this.environment)) () -> new DependsOnDatabaseInitializationPostProcessor(this.environment))
.getBeanDefinition()); .getBeanDefinition());
} }
static class DependsOnDataSourceInitializationPostProcessor implements BeanFactoryPostProcessor { static class DependsOnDatabaseInitializationPostProcessor implements BeanFactoryPostProcessor {
private final Environment environment; private final Environment environment;
DependsOnDataSourceInitializationPostProcessor(Environment environment) { DependsOnDatabaseInitializationPostProcessor(Environment environment) {
this.environment = environment; this.environment = environment;
} }
@Override @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
Set<String> detectedDataSourceInitializers = detectDataSourceInitializers(beanFactory); Set<String> detectedDatabaseInitializers = detectDatabaseInitializers(beanFactory);
for (String dependentDefinitionName : detectDependsOnDataSourceInitialization(beanFactory, if (detectedDatabaseInitializers.isEmpty()) {
return;
}
for (String dependentDefinitionName : detectDependsOnDatabaseInitialization(beanFactory,
this.environment)) { this.environment)) {
BeanDefinition definition = getBeanDefinition(dependentDefinitionName, beanFactory); BeanDefinition definition = getBeanDefinition(dependentDefinitionName, beanFactory);
String[] dependencies = definition.getDependsOn(); String[] dependencies = definition.getDependsOn();
for (String dependencyName : detectedDataSourceInitializers) { for (String dependencyName : detectedDatabaseInitializers) {
dependencies = StringUtils.addStringToArray(dependencies, dependencyName); dependencies = StringUtils.addStringToArray(dependencies, dependencyName);
} }
definition.setDependsOn(dependencies); definition.setDependsOn(dependencies);
} }
} }
private Set<String> detectDataSourceInitializers(ConfigurableListableBeanFactory beanFactory) { private Set<String> detectDatabaseInitializers(ConfigurableListableBeanFactory beanFactory) {
List<DataSourceInitializerDetector> detectors = instantiateDetectors(beanFactory, this.environment, List<DatabaseInitializerDetector> detectors = instantiateDetectors(beanFactory, this.environment,
DataSourceInitializerDetector.class); DatabaseInitializerDetector.class);
Set<String> detected = new HashSet<>(); Set<String> detected = new HashSet<>();
for (DataSourceInitializerDetector detector : detectors) { for (DatabaseInitializerDetector detector : detectors) {
for (String initializerName : detector.detect(beanFactory)) { for (String initializerName : detector.detect(beanFactory)) {
detected.add(initializerName); detected.add(initializerName);
beanFactory.getBeanDefinition(initializerName) beanFactory.getBeanDefinition(initializerName)
.setAttribute(DataSourceInitializerDetector.class.getName(), detector.getClass().getName()); .setAttribute(DatabaseInitializerDetector.class.getName(), detector.getClass().getName());
} }
} }
detected = Collections.unmodifiableSet(detected); detected = Collections.unmodifiableSet(detected);
for (DataSourceInitializerDetector detector : detectors) { for (DatabaseInitializerDetector detector : detectors) {
detector.detectionComplete(beanFactory, detected); detector.detectionComplete(beanFactory, detected);
} }
return detected; return detected;
} }
private Collection<String> detectDependsOnDataSourceInitialization(ConfigurableListableBeanFactory beanFactory, private Collection<String> detectDependsOnDatabaseInitialization(ConfigurableListableBeanFactory beanFactory,
Environment environment) { Environment environment) {
List<DependsOnDataSourceInitializationDetector> detectors = instantiateDetectors(beanFactory, environment, List<DependsOnDatabaseInitializationDetector> detectors = instantiateDetectors(beanFactory, environment,
DependsOnDataSourceInitializationDetector.class); DependsOnDatabaseInitializationDetector.class);
Set<String> dependentUponDataSourceInitialization = new HashSet<>(); Set<String> dependentUponDatabaseInitialization = new HashSet<>();
for (DependsOnDataSourceInitializationDetector detector : detectors) { for (DependsOnDatabaseInitializationDetector detector : detectors) {
dependentUponDataSourceInitialization.addAll(detector.detect(beanFactory)); dependentUponDatabaseInitialization.addAll(detector.detect(beanFactory));
} }
return dependentUponDataSourceInitialization; return dependentUponDatabaseInitialization;
} }
private <T> List<T> instantiateDetectors(ConfigurableListableBeanFactory beanFactory, Environment environment, private <T> List<T> instantiateDetectors(ConfigurableListableBeanFactory beanFactory, Environment environment,
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.jdbc.init.dependency; package org.springframework.boot.sql.init.dependency;
import java.util.Set; import java.util.Set;
...@@ -23,14 +23,14 @@ import javax.sql.DataSource; ...@@ -23,14 +23,14 @@ import javax.sql.DataSource;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
/** /**
* Detects beans that initialize a {@link DataSource}. Implementations should be * Detects beans that initialize an SQL database. Implementations should be registered in
* registered in {@code META-INF/spring.factories} under the key * {@code META-INF/spring.factories} under the key
* {@code org.springframework.boot.jdbc.init.DependsOnDataSourceInitializationDetector}. * {@code org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector}.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 2.5.0 * @since 2.5.0
*/ */
public interface DataSourceInitializerDetector { public interface DatabaseInitializerDetector {
/** /**
* Detect beans defined in the given {@code beanFactory} that initialize a * Detect beans defined in the given {@code beanFactory} that initialize a
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.jdbc.init.dependency; package org.springframework.boot.sql.init.dependency;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
...@@ -25,9 +25,8 @@ import java.lang.annotation.Target; ...@@ -25,9 +25,8 @@ import java.lang.annotation.Target;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
/** /**
* Indicate that a bean's creation and initialization depends upon data source * Indicate that a bean's creation and initialization depends upon database initialization
* initialization having completed. May be used on a bean's class or its * having completed. May be used on a bean's class or its {@link Bean @Bean} definition.
* {@link Bean @Bean} definition.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 2.5.0 * @since 2.5.0
...@@ -35,6 +34,6 @@ import org.springframework.context.annotation.Bean; ...@@ -35,6 +34,6 @@ import org.springframework.context.annotation.Bean;
@Target({ ElementType.TYPE, ElementType.METHOD }) @Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface DependsOnDataSourceInitialization { public @interface DependsOnDatabaseInitialization {
} }
...@@ -14,30 +14,27 @@ ...@@ -14,30 +14,27 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.jdbc.init.dependency; package org.springframework.boot.sql.init.dependency;
import java.util.Set; import java.util.Set;
import javax.sql.DataSource;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
/** /**
* Detects beans that depend on {@link DataSource} initialization. Implementations should * Detects beans that depend on database initialization. Implementations should be
* be registered in {@code META-INF/spring.factories} under the key * registered in {@code META-INF/spring.factories} under the key
* {@code org.springframework.boot.jdbc.init.DependsOnDataSourceInitializationDetector}. * {@code org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector}.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 2.5.0 * @since 2.5.0
*/ */
public interface DependsOnDataSourceInitializationDetector { public interface DependsOnDatabaseInitializationDetector {
/** /**
* Detect beans defined in the given {@code beanFactory} that depend on * Detect beans defined in the given {@code beanFactory} that depend on database
* {@link DataSource} initialization. If no beans are detected, an empty set is * initialization. If no beans are detected, an empty set is returned.
* returned.
* @param beanFactory bean factory to examine * @param beanFactory bean factory to examine
* @return names of any beans that depend upon {@code DataSource} initialization * @return names of any beans that depend upon database initialization
*/ */
Set<String> detect(ConfigurableListableBeanFactory beanFactory); Set<String> detect(ConfigurableListableBeanFactory beanFactory);
......
...@@ -15,6 +15,6 @@ ...@@ -15,6 +15,6 @@
*/ */
/** /**
* Infrastructure for establishing {@code DataSource} initialization bean dependencies. * Infrastructure for establishing database initialization bean dependencies.
*/ */
package org.springframework.boot.jdbc.init.dependency; package org.springframework.boot.sql.init.dependency;
...@@ -79,16 +79,17 @@ org.springframework.boot.liquibase.LiquibaseChangelogMissingFailureAnalyzer ...@@ -79,16 +79,17 @@ org.springframework.boot.liquibase.LiquibaseChangelogMissingFailureAnalyzer
org.springframework.boot.diagnostics.FailureAnalysisReporter=\ org.springframework.boot.diagnostics.FailureAnalysisReporter=\
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter
# DataSource Initializer Detectors # Database Initializer Detectors
org.springframework.boot.jdbc.init.dependency.DataSourceInitializerDetector=\ org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector=\
org.springframework.boot.flyway.FlywayDataSourceInitializerDetector,\ org.springframework.boot.flyway.FlywayDatabaseInitializerDetector,\
org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializerDetector,\ org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializerDetector,\
org.springframework.boot.liquibase.LiquibaseDataSourceInitializerDetector,\ org.springframework.boot.liquibase.LiquibaseDatabaseInitializerDetector,\
org.springframework.boot.orm.jpa.JpaDataSourceInitializerDetector org.springframework.boot.orm.jpa.JpaDatabaseInitializerDetector,\
org.springframework.boot.r2dbc.init.R2dbcScriptDatabaseInitializerDetector
# Depends On DataSource Initialization Detectors # Depends On Database Initialization Detectors
org.springframework.boot.jdbc.init.dependency.DependsOnDataSourceInitializationDetector=\ org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector=\
org.springframework.boot.jdbc.init.dependency.AnnotationDependsOnDataSourceInitializationDetector,\ org.springframework.boot.sql.init.dependency.AnnotationDependsOnDatabaseInitializationDetector,\
org.springframework.boot.jdbc.SpringJdbcDependsOnDataSourceInitializationDetector,\ org.springframework.boot.jdbc.SpringJdbcDependsOnDatabaseInitializationDetector,\
org.springframework.boot.jooq.JooqDependsOnDataSourceInitializationDetector,\ org.springframework.boot.jooq.JooqDependsOnDatabaseInitializationDetector,\
org.springframework.boot.orm.jpa.JpaDependsOnDataSourceInitializationDetector org.springframework.boot.orm.jpa.JpaDependsOnDatabaseInitializationDetector
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.jdbc.init.dependency; package org.springframework.boot.sql.init.dependency;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
...@@ -51,55 +51,54 @@ import static org.mockito.Mockito.reset; ...@@ -51,55 +51,54 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
/** /**
* Tests for {@link DataSourceInitializationDependencyConfigurer}. * Tests for {@link DatabaseInitializationDependencyConfigurer}.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
class DataSourceInitializationDependencyConfigurerTests { class DatabaseInitializationDependencyConfigurerTests {
private final ConfigurableEnvironment environment = new MockEnvironment(); private final ConfigurableEnvironment environment = new MockEnvironment();
DataSourceInitializerDetector dataSourceInitializerDetector = MockedDataSourceInitializerDetector.mock; DatabaseInitializerDetector databaseInitializerDetector = MockedDatabaseInitializerDetector.mock;
DependsOnDataSourceInitializationDetector dependsOnDataSourceInitializationDetector = MockedDependsOnDataSourceInitializationDetector.mock; DependsOnDatabaseInitializationDetector dependsOnDatabaseInitializationDetector = MockedDependsOnDatabaseInitializationDetector.mock;
@TempDir @TempDir
File temp; File temp;
@BeforeEach @BeforeEach
void resetMocks() { void resetMocks() {
reset(MockedDataSourceInitializerDetector.mock, MockedDependsOnDataSourceInitializationDetector.mock); reset(MockedDatabaseInitializerDetector.mock, MockedDependsOnDatabaseInitializationDetector.mock);
} }
@Test @Test
void whenDetectorsAreCreatedThenTheEnvironmentCanBeInjected() { void whenDetectorsAreCreatedThenTheEnvironmentCanBeInjected() {
performDetection(Arrays.asList(ConstructorInjectionDataSourceInitializerDetector.class, performDetection(Arrays.asList(ConstructorInjectionDatabaseInitializerDetector.class,
ConstructorInjectionDependsOnDataSourceInitializationDetector.class), (context) -> { ConstructorInjectionDependsOnDatabaseInitializationDetector.class), (context) -> {
context.refresh(); context.refresh();
assertThat(ConstructorInjectionDataSourceInitializerDetector.environment) assertThat(ConstructorInjectionDatabaseInitializerDetector.environment).isEqualTo(this.environment);
.isEqualTo(this.environment); assertThat(ConstructorInjectionDependsOnDatabaseInitializationDetector.environment)
assertThat(ConstructorInjectionDependsOnDataSourceInitializationDetector.environment)
.isEqualTo(this.environment); .isEqualTo(this.environment);
}); });
} }
@Test @Test
void whenDependenciesAreConfiguredThenBeansThatDependUponDataSourceInitializationDependUponDetectedDataSourceInitializers() { void whenDependenciesAreConfiguredThenBeansThatDependUponDatabaseInitializationDependUponDetectedDatabaseInitializers() {
BeanDefinition alpha = BeanDefinitionBuilder.genericBeanDefinition(String.class).getBeanDefinition(); BeanDefinition alpha = BeanDefinitionBuilder.genericBeanDefinition(String.class).getBeanDefinition();
BeanDefinition bravo = BeanDefinitionBuilder.genericBeanDefinition(String.class).getBeanDefinition(); BeanDefinition bravo = BeanDefinitionBuilder.genericBeanDefinition(String.class).getBeanDefinition();
performDetection(Arrays.asList(MockedDataSourceInitializerDetector.class, performDetection(Arrays.asList(MockedDatabaseInitializerDetector.class,
MockedDependsOnDataSourceInitializationDetector.class), (context) -> { MockedDependsOnDatabaseInitializationDetector.class), (context) -> {
context.registerBeanDefinition("alpha", alpha); context.registerBeanDefinition("alpha", alpha);
context.registerBeanDefinition("bravo", bravo); context.registerBeanDefinition("bravo", bravo);
given(this.dataSourceInitializerDetector.detect(context.getBeanFactory())) given(this.databaseInitializerDetector.detect(context.getBeanFactory()))
.willReturn(Collections.singleton("alpha")); .willReturn(Collections.singleton("alpha"));
given(this.dependsOnDataSourceInitializationDetector.detect(context.getBeanFactory())) given(this.dependsOnDatabaseInitializationDetector.detect(context.getBeanFactory()))
.willReturn(Collections.singleton("bravo")); .willReturn(Collections.singleton("bravo"));
context.refresh(); context.refresh();
assertThat(alpha.getAttribute(DataSourceInitializerDetector.class.getName())) assertThat(alpha.getAttribute(DatabaseInitializerDetector.class.getName()))
.isEqualTo(MockedDataSourceInitializerDetector.class.getName()); .isEqualTo(MockedDatabaseInitializerDetector.class.getName());
assertThat(bravo.getAttribute(DataSourceInitializerDetector.class.getName())).isNull(); assertThat(bravo.getAttribute(DatabaseInitializerDetector.class.getName())).isNull();
verify(this.dataSourceInitializerDetector).detectionComplete(context.getBeanFactory(), verify(this.databaseInitializerDetector).detectionComplete(context.getBeanFactory(),
Collections.singleton("alpha")); Collections.singleton("alpha"));
assertThat(bravo.getDependsOn()).containsExactly("alpha"); assertThat(bravo.getDependsOn()).containsExactly("alpha");
}); });
...@@ -118,17 +117,17 @@ class DataSourceInitializationDependencyConfigurerTests { ...@@ -118,17 +117,17 @@ class DataSourceInitializationDependencyConfigurerTests {
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@Import(DataSourceInitializationDependencyConfigurer.class) @Import(DatabaseInitializationDependencyConfigurer.class)
static class DependencyConfigurerConfiguration { static class DependencyConfigurerConfiguration {
} }
static class ConstructorInjectionDataSourceInitializerDetector implements DataSourceInitializerDetector { static class ConstructorInjectionDatabaseInitializerDetector implements DatabaseInitializerDetector {
private static Environment environment; private static Environment environment;
ConstructorInjectionDataSourceInitializerDetector(Environment environment) { ConstructorInjectionDatabaseInitializerDetector(Environment environment) {
ConstructorInjectionDataSourceInitializerDetector.environment = environment; ConstructorInjectionDatabaseInitializerDetector.environment = environment;
} }
@Override @Override
...@@ -138,13 +137,13 @@ class DataSourceInitializationDependencyConfigurerTests { ...@@ -138,13 +137,13 @@ class DataSourceInitializationDependencyConfigurerTests {
} }
static class ConstructorInjectionDependsOnDataSourceInitializationDetector static class ConstructorInjectionDependsOnDatabaseInitializationDetector
implements DependsOnDataSourceInitializationDetector { implements DependsOnDatabaseInitializationDetector {
private static Environment environment; private static Environment environment;
ConstructorInjectionDependsOnDataSourceInitializationDetector(Environment environment) { ConstructorInjectionDependsOnDatabaseInitializationDetector(Environment environment) {
ConstructorInjectionDependsOnDataSourceInitializationDetector.environment = environment; ConstructorInjectionDependsOnDatabaseInitializationDetector.environment = environment;
} }
@Override @Override
...@@ -154,40 +153,40 @@ class DataSourceInitializationDependencyConfigurerTests { ...@@ -154,40 +153,40 @@ class DataSourceInitializationDependencyConfigurerTests {
} }
static class MockedDataSourceInitializerDetector implements DataSourceInitializerDetector { static class MockedDatabaseInitializerDetector implements DatabaseInitializerDetector {
private static DataSourceInitializerDetector mock = Mockito.mock(DataSourceInitializerDetector.class); private static DatabaseInitializerDetector mock = Mockito.mock(DatabaseInitializerDetector.class);
@Override @Override
public Set<String> detect(ConfigurableListableBeanFactory beanFactory) { public Set<String> detect(ConfigurableListableBeanFactory beanFactory) {
return MockedDataSourceInitializerDetector.mock.detect(beanFactory); return MockedDatabaseInitializerDetector.mock.detect(beanFactory);
} }
@Override @Override
public void detectionComplete(ConfigurableListableBeanFactory beanFactory, public void detectionComplete(ConfigurableListableBeanFactory beanFactory,
Set<String> dataSourceInitializerNames) { Set<String> databaseInitializerNames) {
mock.detectionComplete(beanFactory, dataSourceInitializerNames); mock.detectionComplete(beanFactory, databaseInitializerNames);
} }
} }
static class MockedDependsOnDataSourceInitializationDetector implements DependsOnDataSourceInitializationDetector { static class MockedDependsOnDatabaseInitializationDetector implements DependsOnDatabaseInitializationDetector {
private static DependsOnDataSourceInitializationDetector mock = Mockito private static DependsOnDatabaseInitializationDetector mock = Mockito
.mock(DependsOnDataSourceInitializationDetector.class); .mock(DependsOnDatabaseInitializationDetector.class);
@Override @Override
public Set<String> detect(ConfigurableListableBeanFactory beanFactory) { public Set<String> detect(ConfigurableListableBeanFactory beanFactory) {
return MockedDependsOnDataSourceInitializationDetector.mock.detect(beanFactory); return MockedDependsOnDatabaseInitializationDetector.mock.detect(beanFactory);
} }
} }
static class DetectorSpringFactoriesClassLoader extends ClassLoader { static class DetectorSpringFactoriesClassLoader extends ClassLoader {
private final Set<Class<DataSourceInitializerDetector>> dataSourceInitializerDetectors = new HashSet<>(); private final Set<Class<DatabaseInitializerDetector>> databaseInitializerDetectors = new HashSet<>();
private final Set<Class<DependsOnDataSourceInitializationDetector>> dependsOnDataSourceInitializationDetectors = new HashSet<>(); private final Set<Class<DependsOnDatabaseInitializationDetector>> dependsOnDatabaseInitializationDetectors = new HashSet<>();
private final File temp; private final File temp;
...@@ -197,12 +196,12 @@ class DataSourceInitializationDependencyConfigurerTests { ...@@ -197,12 +196,12 @@ class DataSourceInitializationDependencyConfigurerTests {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
void register(Class<?> detector) { void register(Class<?> detector) {
if (DataSourceInitializerDetector.class.isAssignableFrom(detector)) { if (DatabaseInitializerDetector.class.isAssignableFrom(detector)) {
this.dataSourceInitializerDetectors.add((Class<DataSourceInitializerDetector>) detector); this.databaseInitializerDetectors.add((Class<DatabaseInitializerDetector>) detector);
} }
else if (DependsOnDataSourceInitializationDetector.class.isAssignableFrom(detector)) { else if (DependsOnDatabaseInitializationDetector.class.isAssignableFrom(detector)) {
this.dependsOnDataSourceInitializationDetectors this.dependsOnDatabaseInitializationDetectors
.add((Class<DependsOnDataSourceInitializationDetector>) detector); .add((Class<DependsOnDatabaseInitializationDetector>) detector);
} }
else { else {
throw new IllegalArgumentException("Unsupported detector type '" + detector.getName() + "'"); throw new IllegalArgumentException("Unsupported detector type '" + detector.getName() + "'");
...@@ -215,10 +214,10 @@ class DataSourceInitializationDependencyConfigurerTests { ...@@ -215,10 +214,10 @@ class DataSourceInitializationDependencyConfigurerTests {
return super.findResources(name); return super.findResources(name);
} }
Properties properties = new Properties(); Properties properties = new Properties();
properties.put(DataSourceInitializerDetector.class.getName(), String.join(",", properties.put(DatabaseInitializerDetector.class.getName(), String.join(",",
this.dataSourceInitializerDetectors.stream().map(Class::getName).collect(Collectors.toList()))); this.databaseInitializerDetectors.stream().map(Class::getName).collect(Collectors.toList())));
properties.put(DependsOnDataSourceInitializationDetector.class.getName(), properties.put(DependsOnDatabaseInitializationDetector.class.getName(),
String.join(",", this.dependsOnDataSourceInitializationDetectors.stream().map(Class::getName) String.join(",", this.dependsOnDatabaseInitializationDetectors.stream().map(Class::getName)
.collect(Collectors.toList()))); .collect(Collectors.toList())));
File springFactories = new File(this.temp, "spring.factories"); File springFactories = new File(this.temp, "spring.factories");
try (FileWriter writer = new FileWriter(springFactories)) { try (FileWriter writer = new FileWriter(springFactories)) {
......
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