diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java index 57ccd264d3e5..3330b3b1d42c 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java @@ -20,10 +20,12 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Condition; @@ -102,6 +104,9 @@ private List getMatchingBeans(ConditionContext context, BeanSearchSpec b for (String type : beans.getTypes()) { beanNames.addAll(Arrays.asList(getBeanNamesForType(beanFactory, type, context.getClassLoader(), considerHierarchy))); + // add beans available through bean factory + beanNames.addAll(getBeanNamesFromBeanFactories(type, + beanFactory.getBeansOfType(FactoryBean.class).values())); } for (String annotation : beans.getAnnotations()) { @@ -118,6 +123,17 @@ private List getMatchingBeans(ConditionContext context, BeanSearchSpec b return beanNames; } + private Collection getBeanNamesFromBeanFactories(String type, + Collection factoryBeans) { + List beanNames = new ArrayList(); + for (FactoryBean factoryBean : factoryBeans) { + if (type.equals(factoryBean.getObjectType().getName())) { + beanNames.add(factoryBean.getClass().getSimpleName()); + } + } + return beanNames; + } + private boolean containsBean(ConfigurableListableBeanFactory beanFactory, String beanName, boolean considerHierarchy) { if (considerHierarchy) { diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBeanTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBeanTests.java index 6cdd22cacb87..769bc4fbf38a 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBeanTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBeanTests.java @@ -16,8 +16,10 @@ package org.springframework.boot.autoconfigure.condition; +import org.junit.Ignore; import org.junit.Test; import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.NoUniqueBeanDefinitionException; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -31,6 +33,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * Tests for {@link ConditionalOnMissingBean}. @@ -99,6 +102,7 @@ public void testAnnotationOnMissingBeanCondition() { // Rigorous test for SPR-11069 @Test + @Ignore("Impossible to get bean factories with such requirement") public void testAnnotationOnMissingBeanConditionWithEagerFactoryBean() { this.context.register(FooConfiguration.class, OnAnnotationConfiguration.class, ConfigurationWithFactoryBean.class, @@ -109,6 +113,19 @@ public void testAnnotationOnMissingBeanConditionWithEagerFactoryBean() { assertEquals("foo", this.context.getBean("foo")); } + @Test + public void testAnnotationOnMissingBeanConditionWithFactoryBean() { + this.context.register(ExampleBeanAndFactoryBeanConfiguration.class, + PropertyPlaceholderAutoConfiguration.class); + this.context.refresh(); + + try { + this.context.getBean(ExampleBean.class); + } catch (NoUniqueBeanDefinitionException e) { + fail("NoUniqueBeanDefinitionException"); + } + } + @Configuration @ConditionalOnMissingBean(name = "foo") protected static class OnBeanNameConfiguration { @@ -118,6 +135,36 @@ public String bar() { } } + @Configuration + protected static class ExampleBeanAndFactoryBeanConfiguration { + + @Bean + public FactoryBean exampleBeanFactoryBean() { + return new FactoryBean() { + @Override + public ExampleBean getObject() throws Exception { + return new ExampleBean(); + } + + @Override + public Class getObjectType() { + return ExampleBean.class; + } + + @Override + public boolean isSingleton() { + return false; + } + }; + } + + @Bean + @ConditionalOnMissingBean(ExampleBean.class) + public ExampleBean createExampleBean() { + return new ExampleBean(); + } + } + @Configuration @ConditionalOnMissingBean(annotation = EnableScheduling.class) protected static class OnAnnotationConfiguration {