Skip to content

Commit

Permalink
Merge branch '2.5.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
wilkinsona committed Jun 17, 2021
2 parents 897a719 + 5d20edc commit b1c04e9
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.springframework.boot.util.Instantiator;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.core.type.AnnotationMetadata;
Expand Down Expand Up @@ -84,14 +85,19 @@ private DependsOnDatabaseInitializationPostProcessor createDependsOnDatabaseInit
* {@link BeanFactoryPostProcessor} used to configure database initialization
* dependency relationships.
*/
static class DependsOnDatabaseInitializationPostProcessor implements BeanFactoryPostProcessor {
static class DependsOnDatabaseInitializationPostProcessor implements BeanFactoryPostProcessor, Ordered {

private final Environment environment;

DependsOnDatabaseInitializationPostProcessor(Environment environment) {
this.environment = environment;
}

@Override
public int getOrder() {
return 0;
}

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
Set<String> initializerBeanNames = detectInitializerBeanNames(beanFactory);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.function.Consumer;
Expand All @@ -35,9 +38,11 @@
import org.junit.jupiter.api.io.TempDir;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
Expand Down Expand Up @@ -70,13 +75,38 @@ void resetMocks() {
MockedDependsOnDatabaseInitializationDetector.instance);
}

@Test
void beanFactoryPostProcessorHasOrderAllowingSubsequentPostProcessorsToFineTuneDependencies() {
performDetection(Arrays.asList(MockDatabaseInitializerDetector.class,
MockedDependsOnDatabaseInitializationDetector.class), (context) -> {
BeanDefinition alpha = BeanDefinitionBuilder.genericBeanDefinition(String.class)
.getBeanDefinition();
BeanDefinition bravo = BeanDefinitionBuilder.genericBeanDefinition(String.class)
.getBeanDefinition();
context.register(DependsOnCaptor.class);
context.register(DependencyConfigurerConfiguration.class);
context.registerBeanDefinition("alpha", alpha);
context.registerBeanDefinition("bravo", bravo);
given(MockDatabaseInitializerDetector.instance.detect(context.getBeanFactory()))
.willReturn(Collections.singleton("alpha"));
given(MockedDependsOnDatabaseInitializationDetector.instance.detect(context.getBeanFactory()))
.willReturn(Collections.singleton("bravo"));
context.refresh();
assertThat(DependsOnCaptor.dependsOn).hasEntrySatisfying("bravo",
(dependencies) -> assertThat(dependencies).containsExactly("alpha"));
assertThat(DependsOnCaptor.dependsOn).hasEntrySatisfying("alpha",
(dependencies) -> assertThat(dependencies).isEmpty());
});
}

@Test
void whenDetectorsAreCreatedThenTheEnvironmentCanBeInjected() {
performDetection(Arrays.asList(ConstructorInjectionDatabaseInitializerDetector.class,
ConstructorInjectionDependsOnDatabaseInitializationDetector.class), (context) -> {
BeanDefinition alpha = BeanDefinitionBuilder.genericBeanDefinition(String.class)
.getBeanDefinition();
context.registerBeanDefinition("alpha", alpha);
context.register(DependencyConfigurerConfiguration.class);
context.refresh();
assertThat(ConstructorInjectionDatabaseInitializerDetector.environment).isEqualTo(this.environment);
assertThat(ConstructorInjectionDependsOnDatabaseInitializationDetector.environment)
Expand All @@ -96,6 +126,7 @@ void whenDependenciesAreConfiguredThenBeansThatDependUponDatabaseInitializationD
.willReturn(Collections.singleton("alpha"));
given(MockedDependsOnDatabaseInitializationDetector.instance.detect(context.getBeanFactory()))
.willReturn(Collections.singleton("bravo"));
context.register(DependencyConfigurerConfiguration.class);
context.refresh();
assertThat(alpha.getAttribute(DatabaseInitializerDetector.class.getName()))
.isEqualTo(MockDatabaseInitializerDetector.class.getName());
Expand Down Expand Up @@ -123,6 +154,7 @@ void whenDependenciesAreConfiguredDetectedDatabaseInitializersAreInitializedInCo
context.registerBeanDefinition("alpha", alpha);
context.registerBeanDefinition("bravo", bravo);
context.registerBeanDefinition("charlie", charlie);
context.register(DependencyConfigurerConfiguration.class);
context.refresh();
assertThat(charlie.getDependsOn()).containsExactly("alpha", "bravo");
assertThat(bravo.getDependsOn()).containsExactly("alpha");
Expand All @@ -137,7 +169,6 @@ private void performDetection(Collection<Class<?>> detectors,
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
context.setEnvironment(this.environment);
context.setClassLoader(detectorSpringFactories);
context.register(DependencyConfigurerConfiguration.class);
contextCallback.accept(context);
}
}
Expand Down Expand Up @@ -270,4 +301,28 @@ public Enumeration<URL> getResources(String name) throws IOException {

}

@Configuration(proxyBeanMethods = false)
static class DependsOnCaptor {

static final Map<String, List<String>> dependsOn = new HashMap<>();

@Bean
static BeanFactoryPostProcessor dependsOnCapturingPostProcessor() {
return (beanFactory) -> {
dependsOn.clear();
for (String name : beanFactory.getBeanDefinitionNames()) {
storeDependsOn(name, beanFactory);
}
};
}

private static void storeDependsOn(String name, ConfigurableListableBeanFactory beanFactory) {
String[] dependsOn = beanFactory.getBeanDefinition(name).getDependsOn();
if (dependsOn != null) {
DependsOnCaptor.dependsOn.put(name, Arrays.asList(dependsOn));
}
}

}

}

0 comments on commit b1c04e9

Please sign in to comment.