diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/BeanTypeRegistry.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/BeanTypeRegistry.java index 96fe2b20bc..c4a7e83382 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/BeanTypeRegistry.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/BeanTypeRegistry.java @@ -33,11 +33,14 @@ import org.springframework.beans.factory.CannotLoadBeanClassException; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.SmartInitializingSingleton; +import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.core.ResolvableType; +import org.springframework.core.type.MethodMetadata; +import org.springframework.core.type.StandardMethodMetadata; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; @@ -108,12 +111,7 @@ abstract class BeanTypeRegistry { private Class getConfigurationClassFactoryBeanGeneric( ConfigurableListableBeanFactory beanFactory, BeanDefinition definition, String name) throws Exception { - BeanDefinition factoryDefinition = beanFactory.getBeanDefinition(definition - .getFactoryBeanName()); - Class factoryClass = ClassUtils.forName(factoryDefinition.getBeanClassName(), - beanFactory.getBeanClassLoader()); - Method method = ReflectionUtils.findMethod(factoryClass, - definition.getFactoryMethodName()); + Method method = getFactoryMethod(beanFactory, definition); Class generic = ResolvableType.forMethodReturnType(method) .as(FactoryBean.class).resolveGeneric(); if ((generic == null || generic.equals(Object.class)) @@ -124,6 +122,24 @@ abstract class BeanTypeRegistry { return generic; } + private Method getFactoryMethod(ConfigurableListableBeanFactory beanFactory, + BeanDefinition definition) throws Exception { + if (definition instanceof AnnotatedBeanDefinition) { + MethodMetadata factoryMethodMetadata = ((AnnotatedBeanDefinition) definition) + .getFactoryMethodMetadata(); + if (factoryMethodMetadata instanceof StandardMethodMetadata) { + return ((StandardMethodMetadata) factoryMethodMetadata) + .getIntrospectedMethod(); + } + } + BeanDefinition factoryDefinition = beanFactory.getBeanDefinition(definition + .getFactoryBeanName()); + Class factoryClass = ClassUtils.forName(factoryDefinition.getBeanClassName(), + beanFactory.getBeanClassLoader()); + return ReflectionUtils + .findMethod(factoryClass, definition.getFactoryMethodName()); + } + private Class getDirectFactoryBeanGeneric( ConfigurableListableBeanFactory beanFactory, BeanDefinition definition, String name) throws ClassNotFoundException, LinkageError { 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 c58edd25bb..c9d22f208d 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 @@ -18,9 +18,11 @@ package org.springframework.boot.autoconfigure.condition; import org.junit.Test; import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -127,6 +129,17 @@ public class ConditionalOnMissingBeanTests { equalTo("fromFactory")); } + @Test + public void testOnMissingBeanConditionWithFactoryBeanWithBeanMethodArguments() { + this.context.register(FactoryBeanWithBeanMethodArgumentsConfiguration.class, + ConditionalOnFactoryBean.class, + PropertyPlaceholderAutoConfiguration.class); + EnvironmentTestUtils.addEnvironment(this.context, "theValue:foo"); + this.context.refresh(); + assertThat(this.context.getBean(ExampleBean.class).toString(), + equalTo("fromFactory")); + } + @Test public void testOnMissingBeanConditionWithConcreteFactoryBean() { this.context.register(ConcreteFactoryBeanConfiguration.class, @@ -227,6 +240,15 @@ public class ConditionalOnMissingBeanTests { } } + @Configuration + protected static class FactoryBeanWithBeanMethodArgumentsConfiguration { + @Bean + public FactoryBean exampleBeanFactoryBean( + @Value("${theValue}") String value) { + return new ExampleFactoryBean(value); + } + } + @Configuration protected static class ConcreteFactoryBeanConfiguration { @Bean