-
Notifications
You must be signed in to change notification settings - Fork 38.9k
Description
Andy Wilkinson opened SPR-16217 and commented
ConfigurationClassParser populates its knownSuperclasses map during the configuration phase of condition evaluation. This means that a subclass that has a register bean phase condition can cause the superclass to be skipped even if another superclass that's encountered later would have included it.
The above is perhaps best illustrated by some tests:
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.ConfigurationCondition;
import org.springframework.context.annotation.Import;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class KnownSuperclassesBug {
@Test
public void baseConfigurationIsIncludedWhenFirstSuperclassReferenceIsSkippedInRegisterBeanPhase() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
RegisterBeanPhaseImportingConfiguration.class)) {
context.getBean("someBean");
}
}
@Test
public void baseConfigurationIsIncludedWhenFirstSuperclassReferenceIsSkippedInParseConfigurationPhase() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
ParseConfigurationPhaseImportingConfiguration.class)) {
context.getBean("someBean");
}
}
public static class RegisterBeanPhaseCondition implements ConfigurationCondition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;
}
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.REGISTER_BEAN;
}
}
public static class ParseConfigurationPhaseCondition
implements ConfigurationCondition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;
}
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.PARSE_CONFIGURATION;
}
}
@Import({ RegisterBeanPhaseConditionConfiguration.class, BarConfiguration.class })
public static class RegisterBeanPhaseImportingConfiguration {
}
@Import({ ParseConfigurationPhaseConditionConfiguration.class,
BarConfiguration.class })
public static class ParseConfigurationPhaseImportingConfiguration {
}
public static class BaseConfiguration {
@Bean
public String someBean() {
return "foo";
}
}
@Conditional(RegisterBeanPhaseCondition.class)
public static class RegisterBeanPhaseConditionConfiguration
extends BaseConfiguration {
}
@Conditional(ParseConfigurationPhaseCondition.class)
public static class ParseConfigurationPhaseConditionConfiguration
extends BaseConfiguration {
}
public static class BarConfiguration extends BaseConfiguration {
}
}My expectation is that both tests will pass. As things stand baseConfigurationIsIncludedWhenFirstSuperclassReferenceIsSkippedInRegisterBeanPhase fails and baseConfigurationIsIncludedWhenFirstSuperclassReferenceIsSkippedInParseConfigurationPhase() passes.
The first test fails because RegisterBeanPhaseConditionConfiguration is processed and BaseConfiguration is added to the knownSuperclasses map. When BarConfiguration is processed BaseConfiguration is already in the knownSuperclasses map so its "import" via BarConfiguration is lost. When the register bean phase condition on RegisterBeanPhaseConditionConfiguration is evaluated it doesn't match so it's skipped along with BaseConfiguration that it imports.
Affects: 4.3.12, 5.0.1
Reference URL: spring-projects/spring-boot#11063
Issue Links:
- ImportAware.setImportMetadata not invoked if import inherited from superclass with negative condition [SPR-14972] #19538 ImportAware.setImportMetadata not invoked if import inherited from superclass with negative condition
- TrackedConditionEvaluator skips loading bean definitions for configuration classes that should not be skipped [SPR-17153] #21690 TrackedConditionEvaluator skips loading bean definitions for configuration classes that should not be skipped
Referenced from: commits 47383fc, 08c95fb
1 votes, 5 watchers