Consider ancestors when finding primary beans for ConditionalOnSingleCandidate

Closes gh-6559
pull/6855/head
Andy Wilkinson 8 years ago
parent 75c1e50c5a
commit a5c6b0954d

@ -99,7 +99,8 @@ class OnBeanCondition extends SpringBootCondition implements ConfigurationCondit
return ConditionOutcome.noMatch(
"@ConditionalOnSingleCandidate " + spec + " found no beans");
}
else if (!hasSingleAutowireCandidate(context.getBeanFactory(), matching)) {
else if (!hasSingleAutowireCandidate(context.getBeanFactory(), matching,
spec.getStrategy() == SearchStrategy.ALL)) {
return ConditionOutcome.noMatch("@ConditionalOnSingleCandidate " + spec
+ " found no primary candidate amongst the" + " following "
+ matching);
@ -225,16 +226,19 @@ class OnBeanCondition extends SpringBootCondition implements ConfigurationCondit
}
private boolean hasSingleAutowireCandidate(
ConfigurableListableBeanFactory beanFactory, List<String> beanNames) {
ConfigurableListableBeanFactory beanFactory, List<String> beanNames,
boolean considerHierarchy) {
return (beanNames.size() == 1
|| getPrimaryBeans(beanFactory, beanNames).size() == 1);
|| getPrimaryBeans(beanFactory, beanNames, considerHierarchy)
.size() == 1);
}
private List<String> getPrimaryBeans(ConfigurableListableBeanFactory beanFactory,
List<String> beanNames) {
List<String> beanNames, boolean considerHierarchy) {
List<String> primaryBeans = new ArrayList<String>();
for (String beanName : beanNames) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
BeanDefinition beanDefinition = findBeanDefinition(beanFactory, beanName,
considerHierarchy);
if (beanDefinition != null && beanDefinition.isPrimary()) {
primaryBeans.add(beanName);
}
@ -242,6 +246,20 @@ class OnBeanCondition extends SpringBootCondition implements ConfigurationCondit
return primaryBeans;
}
private BeanDefinition findBeanDefinition(ConfigurableListableBeanFactory beanFactory,
String beanName, boolean considerHierarchy) {
if (beanFactory.containsBeanDefinition(beanName)) {
return beanFactory.getBeanDefinition(beanName);
}
if (considerHierarchy && beanFactory
.getParentBeanFactory() instanceof ConfigurableListableBeanFactory) {
return findBeanDefinition(((ConfigurableListableBeanFactory) beanFactory
.getParentBeanFactory()), beanName, considerHierarchy);
}
return null;
}
private static class BeanSearchSpec {
private final Class<?> annotationType;

@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -35,6 +35,7 @@ import static org.junit.Assert.assertTrue;
* Tests for {@link ConditionalOnSingleCandidate}.
*
* @author Stephane Nicoll
* @author Andy Wilkinson
*/
public class ConditionalOnSingleCandidateTests {
@ -103,6 +104,22 @@ public class ConditionalOnSingleCandidateTests {
load(OnBeanSingleCandidateNoTypeConfiguration.class);
}
@Test
public void singleCandidateMultipleCandidatesInContextHierarchy() {
load(FooPrimaryConfiguration.class, BarConfiguration.class);
AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext();
child.setParent(this.context);
child.register(OnBeanSingleCandidateConfiguration.class);
try {
child.refresh();
assertTrue(child.containsBean("baz"));
assertEquals("foo", child.getBean("baz"));
}
finally {
child.close();
}
}
private void load(Class<?>... classes) {
this.context.register(classes);
this.context.refresh();

Loading…
Cancel
Save