3838import org .springframework .beans .factory .support .BeanDefinitionRegistry ;
3939import org .springframework .beans .factory .support .BeanDefinitionRegistryPostProcessor ;
4040import org .springframework .beans .factory .support .RootBeanDefinition ;
41+ import org .springframework .boot .autoconfigure .condition .ConditionalOnMissingBean ;
42+ import org .springframework .boot .autoconfigure .condition .ConditionalOnSingleCandidate ;
4143import org .springframework .context .ApplicationContext ;
4244import org .springframework .context .ConfigurableApplicationContext ;
4345import org .springframework .context .EnvironmentAware ;
46+ import org .springframework .context .annotation .Bean ;
4447import org .springframework .context .annotation .Configuration ;
4548import org .springframework .context .annotation .DeferredImportSelector ;
4649import org .springframework .context .annotation .Import ;
5558import org .springframework .test .context .ContextCustomizerFactory ;
5659import org .springframework .test .context .MergedContextConfiguration ;
5760import org .springframework .util .Assert ;
61+ import org .springframework .util .ClassUtils ;
5862import org .springframework .util .ObjectUtils ;
63+ import org .springframework .util .StringUtils ;
5964
6065import javax .sql .DataSource ;
6166import java .util .LinkedHashSet ;
@@ -101,12 +106,21 @@ public EmbeddedDatabaseContextCustomizer(Set<DatabaseDefinition> databaseDefinit
101106
102107 @ Override
103108 public void customizeContext (ConfigurableApplicationContext context , MergedContextConfiguration mergedConfig ) {
104- context .addBeanFactoryPostProcessor (new EnvironmentPostProcessor (databaseDefinitions , context .getEnvironment ()));
109+ context .addBeanFactoryPostProcessor (new EnvironmentPostProcessor (context .getEnvironment ()));
105110
106111 BeanDefinitionRegistry registry = getBeanDefinitionRegistry (context );
107112
108- RootBeanDefinition configDefinition = new RootBeanDefinition (EmbeddedDatabaseConfiguration .class );
109- registry .registerBeanDefinition (EmbeddedDatabaseConfiguration .BEAN_NAME , configDefinition );
113+ // these configurations are necessary only for auto-configuration phase
114+ if (databaseDefinitions .size () == 1 ) {
115+ RootBeanDefinition preConfigDefinition = new RootBeanDefinition (SingleDatabaseConfiguration .class );
116+ registry .registerBeanDefinition (SingleDatabaseConfiguration .BEAN_NAME , preConfigDefinition );
117+ } else if (databaseDefinitions .size () > 1 ) {
118+ RootBeanDefinition preConfigDefinition = new RootBeanDefinition (MultipleDatabasesConfiguration .class );
119+ registry .registerBeanDefinition (MultipleDatabasesConfiguration .BEAN_NAME , preConfigDefinition );
120+ }
121+
122+ RootBeanDefinition mainConfigDefinition = new RootBeanDefinition (EmbeddedDatabaseConfiguration .class );
123+ registry .registerBeanDefinition (EmbeddedDatabaseConfiguration .BEAN_NAME , mainConfigDefinition );
110124
111125 RootBeanDefinition registrarDefinition = new RootBeanDefinition (EmbeddedDatabaseRegistrar .class );
112126 registrarDefinition .getConstructorArgumentValues ().addIndexedArgumentValue (0 , databaseDefinitions );
@@ -132,22 +146,17 @@ public int hashCode() {
132146
133147 protected static class EnvironmentPostProcessor implements BeanDefinitionRegistryPostProcessor {
134148
135- private final Set <DatabaseDefinition > databaseDefinitions ;
136149 private final ConfigurableEnvironment environment ;
137150
138- public EnvironmentPostProcessor (Set <DatabaseDefinition > databaseDefinitions , ConfigurableEnvironment environment ) {
139- this .databaseDefinitions = databaseDefinitions ;
151+ public EnvironmentPostProcessor (ConfigurableEnvironment environment ) {
140152 this .environment = environment ;
141153 }
142154
143155 @ Override
144156 public void postProcessBeanDefinitionRegistry (BeanDefinitionRegistry registry ) {
145- Replace zonkyDatabaseReplace = getDatabaseReplaceMode (environment , databaseDefinitions );
146- String springDatabaseReplace = zonkyDatabaseReplace == Replace .NONE ? "NONE" : "AUTO_CONFIGURED" ;
147-
148157 environment .getPropertySources ().addFirst (new MapPropertySource (
149158 EmbeddedDatabaseContextCustomizer .class .getSimpleName (),
150- ImmutableMap .of ("spring.test.database.replace" , springDatabaseReplace )));
159+ ImmutableMap .of ("spring.test.database.replace" , "NONE" )));
151160 }
152161
153162 @ Override
@@ -156,6 +165,65 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
156165 }
157166 }
158167
168+ @ Configuration
169+ @ Import (PreAutoConfigurationImportSelector .class )
170+ protected static class SingleDatabaseConfiguration {
171+
172+ protected static final String BEAN_NAME = SingleDatabaseConfiguration .class .getName ();
173+
174+ }
175+
176+ @ Configuration
177+ @ Import (PreAutoConfigurationImportSelector .class )
178+ protected static class MultipleDatabasesConfiguration {
179+
180+ protected static final String BEAN_NAME = MultipleDatabasesConfiguration .class .getName ();
181+
182+ }
183+
184+ protected static class PreAutoConfigurationImportSelector implements DeferredImportSelector , Ordered {
185+
186+ @ Override
187+ public String [] selectImports (AnnotationMetadata annotationMetadata ) {
188+ if (!ClassUtils .isPresent ("org.springframework.boot.autoconfigure.condition.ConditionalOnBean" , null )) {
189+ return new String [0 ];
190+ }
191+ String className = annotationMetadata .getClassName ();
192+ if (SingleDatabaseConfiguration .BEAN_NAME .equals (className )) {
193+ return new String [] { PrimaryDataSourceAutoConfiguration .class .getName () };
194+ }
195+ if (MultipleDatabasesConfiguration .BEAN_NAME .equals (className )) {
196+ return new String [] { PrimaryDataSourceAutoConfiguration .class .getName (), SecondaryDataSourceAutoConfiguration .class .getName () };
197+ }
198+ throw new IllegalStateException ("Unexpected selector configuration class: " + className );
199+ }
200+
201+ @ Override
202+ public int getOrder () {
203+ return Ordered .LOWEST_PRECEDENCE - 3 ;
204+ }
205+ }
206+
207+ @ Configuration
208+ protected static class PrimaryDataSourceAutoConfiguration {
209+
210+ @ Bean
211+ @ ConditionalOnMissingBean
212+ public DataSource embeddedDataSource1 () {
213+ return null ;
214+ }
215+ }
216+
217+ @ Configuration
218+ protected static class SecondaryDataSourceAutoConfiguration {
219+
220+ @ Bean
221+ @ ConditionalOnSingleCandidate
222+ public DataSource embeddedDataSource2 () {
223+ return null ;
224+ }
225+ }
226+
159227 @ Configuration
160228 @ Import (EmbeddedDatabaseConfiguration .Selector .class )
161229 protected static class EmbeddedDatabaseConfiguration {
@@ -199,6 +267,13 @@ public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
199267 "Embedded Database Auto-configuration can only be used with a ConfigurableListableBeanFactory" );
200268 ConfigurableListableBeanFactory beanFactory = (ConfigurableListableBeanFactory ) registry ;
201269
270+ if (registry .containsBeanDefinition ("embeddedDataSource1" )) {
271+ registry .removeBeanDefinition ("embeddedDataSource1" );
272+ }
273+ if (registry .containsBeanDefinition ("embeddedDataSource2" )) {
274+ registry .removeBeanDefinition ("embeddedDataSource2" );
275+ }
276+
202277 Replace replace = getDatabaseReplaceMode (environment , databaseDefinitions );
203278 if (replace == Replace .NONE ) {
204279 logger .info ("The use of the embedded database has been disabled" );
0 commit comments