Skip to content

Commit 316244d

Browse files
committed
Isolated circular import detection for scanned configuration classes
Issue: SPR-14517
1 parent fd9e88d commit 316244d

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public int compare(DeferredImportSelectorHolder o1, DeferredImportSelectorHolder
139139

140140
private final List<String> propertySourceNames = new ArrayList<>();
141141

142-
private final ImportStack importStack = new ImportStack();
142+
private ImportStack importStack = new ImportStack();
143143

144144
private List<DeferredImportSelectorHolder> deferredImportSelectors;
145145

@@ -276,7 +276,16 @@ protected final SourceClass doProcessConfigurationClass(ConfigurationClass confi
276276
// Check the set of scanned definitions for any further config classes and parse recursively if necessary
277277
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
278278
if (ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(), this.metadataReaderFactory)) {
279-
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
279+
// Provide isolated circular import detection for scanned classes,
280+
// since the initial registration did not come explicitly.
281+
ImportStack previousStack = this.importStack;
282+
this.importStack = new ImportStack();
283+
try {
284+
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
285+
}
286+
finally {
287+
this.importStack = previousStack;
288+
}
280289
}
281290
}
282291
}

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
1919
import org.junit.Test;
2020

2121
import org.springframework.beans.factory.support.RootBeanDefinition;
22+
import org.springframework.context.annotation.componentscan.importing.ImportingConfig;
2223
import org.springframework.context.annotation.componentscan.simple.SimpleComponent;
2324

2425
/**
@@ -58,7 +59,7 @@ public void componentScanViaImport() {
5859
@Test
5960
public void componentScanViaImportUsingAsm() {
6061
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
61-
ctx.registerBeanDefinition("config4", new RootBeanDefinition(Config3.class.getName()));
62+
ctx.registerBeanDefinition("config", new RootBeanDefinition(Config3.class.getName()));
6263
ctx.refresh();
6364
ctx.getBean(SimpleComponent.class);
6465
}
@@ -71,6 +72,14 @@ public void componentScanViaImportUsingScan() {
7172
ctx.getBean(SimpleComponent.class);
7273
}
7374

75+
@Test
76+
public void circularImportViaComponentScan() {
77+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
78+
ctx.registerBeanDefinition("config", new RootBeanDefinition(ImportingConfig.class.getName()));
79+
ctx.refresh();
80+
ctx.getBean(SimpleComponent.class);
81+
}
82+
7483

7584
@ComponentScan("org.springframework.context.annotation.componentscan.simple")
7685
static final class Config1 {
@@ -88,6 +97,7 @@ static final class Config3 {
8897

8998

9099
@ComponentScan("org.springframework.context.annotation.componentscan.simple")
100+
@ComponentScan("org.springframework.context.annotation.componentscan.importing")
91101
public static final class ImportedConfig {
92102
}
93103

0 commit comments

Comments
 (0)