Skip to content

Commit 03affa0

Browse files
committed
ConfigurationClassParser detects @bean methods in interface hierarchies as well
Issue: SPR-14288
1 parent 2d85acc commit 03affa0

File tree

2 files changed

+32
-16
lines changed

2 files changed

+32
-16
lines changed

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -303,15 +303,7 @@ protected final SourceClass doProcessConfigurationClass(ConfigurationClass confi
303303
}
304304

305305
// Process default methods on interfaces
306-
for (SourceClass ifc : sourceClass.getInterfaces()) {
307-
beanMethods = ifc.getMetadata().getAnnotatedMethods(Bean.class.getName());
308-
for (MethodMetadata methodMetadata : beanMethods) {
309-
if (!methodMetadata.isAbstract()) {
310-
// A default method or other concrete method on a Java 8+ interface...
311-
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
312-
}
313-
}
314-
}
306+
processInterfaces(configClass, sourceClass);
315307

316308
// Process superclass, if any
317309
if (sourceClass.getMetadata().hasSuperClass()) {
@@ -329,8 +321,6 @@ protected final SourceClass doProcessConfigurationClass(ConfigurationClass confi
329321

330322
/**
331323
* Register member (nested) classes that happen to be configuration classes themselves.
332-
* @param sourceClass the source class to process
333-
* @throws IOException if there is any problem reading metadata from a member class
334324
*/
335325
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
336326
for (SourceClass memberClass : sourceClass.getMemberClasses()) {
@@ -352,6 +342,22 @@ private void processMemberClasses(ConfigurationClass configClass, SourceClass so
352342
}
353343
}
354344

345+
/**
346+
* Register default methods on interfaces implemented by the configuration class.
347+
*/
348+
private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
349+
for (SourceClass ifc : sourceClass.getInterfaces()) {
350+
Set<MethodMetadata> beanMethods = ifc.getMetadata().getAnnotatedMethods(Bean.class.getName());
351+
for (MethodMetadata methodMetadata : beanMethods) {
352+
if (!methodMetadata.isAbstract()) {
353+
// A default method or other concrete method on a Java 8+ interface...
354+
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
355+
}
356+
}
357+
processInterfaces(configClass, ifc);
358+
}
359+
}
360+
355361
/**
356362
* Process the given <code>@PropertySource</code> annotation metadata.
357363
* @param propertySource metadata for the <code>@PropertySource</code> annotation found

spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,17 +1063,27 @@ public void validate() {
10631063
}
10641064
}
10651065

1066-
public interface DefaultMethodsConfig {
1066+
public interface BaseInterface {
10671067

1068-
@Bean
1069-
default ServiceBean serviceBean() {
1070-
return provider().getServiceBean();
1071-
}
1068+
ServiceBean serviceBean();
1069+
}
1070+
1071+
public interface BaseDefaultMethods extends BaseInterface {
10721072

10731073
@Bean
10741074
default ServiceBeanProvider provider() {
10751075
return new ServiceBeanProvider();
10761076
}
1077+
1078+
@Bean
1079+
@Override
1080+
default ServiceBean serviceBean() {
1081+
return provider().getServiceBean();
1082+
}
1083+
}
1084+
1085+
public interface DefaultMethodsConfig extends BaseDefaultMethods {
1086+
10771087
}
10781088

10791089
@Configuration

0 commit comments

Comments
 (0)