Skip to content

Commit 21453b5

Browse files
committed
Ignore scoped targets when finding matching beans
Fixes gh-22038
1 parent 81d6751 commit 21453b5

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@
2424
import java.util.Collections;
2525
import java.util.HashMap;
2626
import java.util.HashSet;
27+
import java.util.Iterator;
2728
import java.util.LinkedHashSet;
2829
import java.util.List;
2930
import java.util.Locale;
3031
import java.util.Map;
3132
import java.util.Set;
3233

34+
import org.springframework.aop.scope.ScopedProxyUtils;
3335
import org.springframework.beans.factory.BeanFactory;
3436
import org.springframework.beans.factory.HierarchicalBeanFactory;
3537
import org.springframework.beans.factory.ListableBeanFactory;
@@ -166,7 +168,13 @@ protected final MatchResult getMatchingBeans(ConditionContext context, Spec<?> s
166168
for (String type : spec.getTypes()) {
167169
Collection<String> typeMatches = getBeanNamesForType(classLoader, considerHierarchy, beanFactory, type,
168170
parameterizedContainers);
169-
typeMatches.removeAll(beansIgnoredByType);
171+
Iterator<String> iterator = typeMatches.iterator();
172+
while (iterator.hasNext()) {
173+
String match = iterator.next();
174+
if (beansIgnoredByType.contains(match) || ScopedProxyUtils.isScopedTarget(match)) {
175+
iterator.remove();
176+
}
177+
}
170178
if (typeMatches.isEmpty()) {
171179
result.recordUnmatchedType(type);
172180
}

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidateTests.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import org.springframework.context.annotation.Bean;
2323
import org.springframework.context.annotation.Configuration;
2424
import org.springframework.context.annotation.Primary;
25+
import org.springframework.context.annotation.Scope;
26+
import org.springframework.context.annotation.ScopedProxyMode;
2527

2628
import static org.assertj.core.api.Assertions.assertThat;
2729

@@ -50,6 +52,16 @@ void singleCandidateOneCandidate() {
5052
});
5153
}
5254

55+
@Test
56+
void singleCandidateOneScopedProxyCandidate() {
57+
this.contextRunner
58+
.withUserConfiguration(AlphaScopedProxyConfiguration.class, OnBeanSingleCandidateConfiguration.class)
59+
.run((context) -> {
60+
assertThat(context).hasBean("consumer");
61+
assertThat(context.getBean("consumer").toString()).isEqualTo("alpha");
62+
});
63+
}
64+
5365
@Test
5466
void singleCandidateInAncestorsOneCandidateInCurrent() {
5567
this.contextRunner.run((parent) -> this.contextRunner
@@ -138,7 +150,7 @@ void singleCandidateMultipleCandidatesInContextHierarchy() {
138150
static class OnBeanSingleCandidateConfiguration {
139151

140152
@Bean
141-
String consumer(String s) {
153+
CharSequence consumer(CharSequence s) {
142154
return s;
143155
}
144156

@@ -149,7 +161,7 @@ String consumer(String s) {
149161
static class OnBeanSingleCandidateInAncestorsConfiguration {
150162

151163
@Bean
152-
String consumer(String s) {
164+
CharSequence consumer(CharSequence s) {
153165
return s;
154166
}
155167

@@ -188,6 +200,17 @@ String alpha() {
188200

189201
}
190202

203+
@Configuration(proxyBeanMethods = false)
204+
static class AlphaScopedProxyConfiguration {
205+
206+
@Bean
207+
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
208+
String alpha() {
209+
return "alpha";
210+
}
211+
212+
}
213+
191214
@Configuration(proxyBeanMethods = false)
192215
static class BravoConfiguration {
193216

0 commit comments

Comments
 (0)