diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java index 4f774c7ed3..8319d24ac2 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java @@ -24,12 +24,14 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; +import org.springframework.aop.scope.ScopedProxyUtils; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.HierarchicalBeanFactory; import org.springframework.beans.factory.ListableBeanFactory; @@ -166,7 +168,13 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat for (String type : spec.getTypes()) { Collection typeMatches = getBeanNamesForType(classLoader, considerHierarchy, beanFactory, type, parameterizedContainers); - typeMatches.removeAll(beansIgnoredByType); + Iterator iterator = typeMatches.iterator(); + while (iterator.hasNext()) { + String match = iterator.next(); + if (beansIgnoredByType.contains(match) || ScopedProxyUtils.isScopedTarget(match)) { + iterator.remove(); + } + } if (typeMatches.isEmpty()) { result.recordUnmatchedType(type); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidateTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidateTests.java index bddc2ec929..1cd9cb7f19 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidateTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidateTests.java @@ -22,6 +22,8 @@ import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; import static org.assertj.core.api.Assertions.assertThat; @@ -50,6 +52,16 @@ class ConditionalOnSingleCandidateTests { }); } + @Test + void singleCandidateOneScopedProxyCandidate() { + this.contextRunner + .withUserConfiguration(AlphaScopedProxyConfiguration.class, OnBeanSingleCandidateConfiguration.class) + .run((context) -> { + assertThat(context).hasBean("consumer"); + assertThat(context.getBean("consumer").toString()).isEqualTo("alpha"); + }); + } + @Test void singleCandidateInAncestorsOneCandidateInCurrent() { this.contextRunner.run((parent) -> this.contextRunner @@ -138,7 +150,7 @@ class ConditionalOnSingleCandidateTests { static class OnBeanSingleCandidateConfiguration { @Bean - String consumer(String s) { + CharSequence consumer(CharSequence s) { return s; } @@ -149,7 +161,7 @@ class ConditionalOnSingleCandidateTests { static class OnBeanSingleCandidateInAncestorsConfiguration { @Bean - String consumer(String s) { + CharSequence consumer(CharSequence s) { return s; } @@ -188,6 +200,17 @@ class ConditionalOnSingleCandidateTests { } + @Configuration(proxyBeanMethods = false) + static class AlphaScopedProxyConfiguration { + + @Bean + @Scope(proxyMode = ScopedProxyMode.INTERFACES) + String alpha() { + return "alpha"; + } + + } + @Configuration(proxyBeanMethods = false) static class BravoConfiguration {