diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java index be137dbd67..95388cc6b5 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java @@ -468,6 +468,9 @@ class ConfigurationClassParser { * the superclass exposure on a different config class with the same superclass. */ private void removeKnownSuperclass(String removedClass, boolean replace) { + String replacedSuperclass = null; + ConfigurationClass replacingClass = null; + Iterator>> it = this.knownSuperclasses.entrySet().iterator(); while (it.hasNext()) { Map.Entry> entry = it.next(); @@ -476,22 +479,29 @@ class ConfigurationClassParser { it.remove(); } else if (replace) { - try { - ConfigurationClass otherClass = entry.getValue().get(0); - SourceClass sourceClass = asSourceClass(otherClass, DEFAULT_EXCLUSION_FILTER).getSuperClass(); - while (!sourceClass.getMetadata().getClassName().equals(entry.getKey()) && - sourceClass.getMetadata().getSuperClassName() != null) { - sourceClass = sourceClass.getSuperClass(); - } - doProcessConfigurationClass(otherClass, sourceClass, DEFAULT_EXCLUSION_FILTER); - } - catch (IOException ex) { - throw new BeanDefinitionStoreException( - "I/O failure while removing configuration class [" + removedClass + "]", ex); - } + replacedSuperclass = entry.getKey(); + replacingClass = entry.getValue().get(0); } } } + + if (replacingClass != null) { + try { + SourceClass sourceClass = asSourceClass(replacingClass, DEFAULT_EXCLUSION_FILTER).getSuperClass(); + while (!sourceClass.getMetadata().getClassName().equals(replacedSuperclass) && + sourceClass.getMetadata().getSuperClassName() != null) { + sourceClass = sourceClass.getSuperClass(); + } + do { + sourceClass = doProcessConfigurationClass(replacingClass, sourceClass, DEFAULT_EXCLUSION_FILTER); + } + while (sourceClass != null); + } + catch (IOException ex) { + throw new BeanDefinitionStoreException( + "I/O failure while removing configuration class [" + removedClass + "]", ex); + } + } } /** diff --git a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationPhasesKnownSuperclassesTests.java b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationPhasesKnownSuperclassesTests.java index 0c33738f53..10d64f79d6 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationPhasesKnownSuperclassesTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationPhasesKnownSuperclassesTests.java @@ -31,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat; /** * @author Andy Wilkinson + * @author Juergen Hoeller * @since 6.2 */ class ConfigurationPhasesKnownSuperclassesTests { @@ -40,6 +41,7 @@ class ConfigurationPhasesKnownSuperclassesTests { try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ParseConfigurationPhase.class)) { assertThat(context.getBean("subclassBean")).isEqualTo("bravo"); assertThat(context.getBean("superclassBean")).isEqualTo("superclass"); + assertThat(context.getBean("baseBean")).isEqualTo("base"); } } @@ -48,12 +50,22 @@ class ConfigurationPhasesKnownSuperclassesTests { try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(RegisterBeanPhase.class)) { assertThat(context.getBean("subclassBean")).isEqualTo("bravo"); assertThat(context.getBean("superclassBean")).isEqualTo("superclass"); + assertThat(context.getBean("baseBean")).isEqualTo("base"); } } @Configuration(proxyBeanMethods = false) - static class Example { + static class Base { + + @Bean + String baseBean() { + return "base"; + } + } + + @Configuration(proxyBeanMethods = false) + static class Example extends Base { @Bean String superclassBean() {