Skip to content

Commit d48fb7f

Browse files
committed
Adjust @Import processing to prioritize local declarations
Closes gh-34805 Signed-off-by: Daeho Kwon <[email protected]>
1 parent 6ff1e2d commit d48fb7f

File tree

2 files changed

+37
-10
lines changed

2 files changed

+37
-10
lines changed

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException
550550
* <p>For example, it is common for a {@code @Configuration} class to declare direct
551551
* {@code @Import}s in addition to meta-imports originating from an {@code @Enable}
552552
* annotation.
553-
* <p>In addition, {@code @Import} annotations declared on interfaces implemented by
553+
* <p>As of Spring Framework 7.0, {@code @Import} annotations declared on interfaces implemented by
554554
* the configuration class are also considered. This allows imports to be triggered
555555
* indirectly via marker interfaces or shared base interfaces.
556556
* @param sourceClass the class to search
@@ -562,17 +562,16 @@ private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, S
562562
throws IOException {
563563

564564
if (visited.add(sourceClass)) {
565+
for (SourceClass ifc : sourceClass.getInterfaces()) {
566+
collectImports(ifc, imports, visited);
567+
}
565568
for (SourceClass annotation : sourceClass.getAnnotations()) {
566569
String annName = annotation.getMetadata().getClassName();
567570
if (!annName.equals(Import.class.getName())) {
568571
collectImports(annotation, imports, visited);
569572
}
570573
}
571574
imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
572-
573-
for (SourceClass ifc : sourceClass.getInterfaces()) {
574-
collectImports(ifc, imports, visited);
575-
}
576575
}
577576
}
578577

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

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,15 +206,24 @@ void invokeAwareMethodsInImportGroup() {
206206

207207
@Test
208208
void importAnnotationOnImplementedInterfaceIsRespected() {
209-
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
210-
context.register(InterfaceBasedConfig.class);
211-
context.refresh();
209+
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
210+
InterfaceBasedConfig.class);
212211

213212
assertThat(context.getBean(ImportedConfig.class)).isNotNull();
214213
assertThat(context.getBean(ImportedBean.class)).isNotNull();
215214
assertThat(context.getBean(ImportedBean.class).name()).isEqualTo("imported");
216215
}
217216

217+
@Test
218+
void localImportShouldOverrideInterfaceImport() {
219+
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
220+
OverridingConfig.class);
221+
222+
assertThat(context.getBean(ImportedConfig.class)).isNotNull();
223+
assertThat(context.getBean(ImportedBean.class)).isNotNull();
224+
assertThat(context.getBean(ImportedBean.class).name()).isEqualTo("from class");
225+
}
226+
218227
@Import(ImportedConfig.class)
219228
interface ConfigImportMarker {
220229
}
@@ -223,9 +232,28 @@ interface ConfigImportMarker {
223232
static class InterfaceBasedConfig implements ConfigImportMarker {
224233
}
225234

235+
@Configuration
236+
static class OverridingConfig implements ConfigImportMarker {
237+
@Bean
238+
ImportedBean importedBean() {
239+
return new ImportedBean("from class");
240+
}
241+
}
242+
226243
static class ImportedBean {
244+
245+
private final String name;
246+
247+
ImportedBean() {
248+
this.name = "imported";
249+
}
250+
251+
ImportedBean(String name) {
252+
this.name = name;
253+
}
254+
227255
String name() {
228-
return "imported";
256+
return name;
229257
}
230258
}
231259

@@ -540,7 +568,7 @@ public static class ChildDeferredImportSelector1 implements DeferredImportSelect
540568
@Override
541569
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
542570
ImportSelectorTests.importFrom.put(getClass(), importingClassMetadata.getClassName());
543-
return new String[] { DeferredImportedSelector3.class.getName() };
571+
return new String[]{DeferredImportedSelector3.class.getName()};
544572
}
545573

546574
@Override

0 commit comments

Comments
 (0)