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 39b7348eca4..013991b20f0 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 @@ -54,6 +54,7 @@ import org.springframework.util.StringUtils; * * * @author Phillip Webb + * @author Andy Wilkinson * @since 1.2.0 */ abstract class BeanTypeRegistry { @@ -115,13 +116,26 @@ abstract class BeanTypeRegistry { definition.getFactoryMethodName()); Class generic = ResolvableType.forMethodReturnType(method) .as(FactoryBean.class).resolveGeneric(); - if ((generic == null || generic.equals(Object.class)) - && definition.hasAttribute(FACTORY_BEAN_OBJECT_TYPE)) { - generic = (Class) definition.getAttribute(FACTORY_BEAN_OBJECT_TYPE); + if (generic == null || generic.equals(Object.class)) { + generic = determineTypeFromDefinitionAttribute(factoryDefinition); } return generic; } + private Class determineTypeFromDefinitionAttribute(BeanDefinition definition) + throws ClassNotFoundException, LinkageError { + if (definition.hasAttribute(FACTORY_BEAN_OBJECT_TYPE)) { + Object attributeObject = definition.getAttribute(FACTORY_BEAN_OBJECT_TYPE); + if (attributeObject instanceof Class) { + return (Class) attributeObject; + } + else if (attributeObject instanceof String) { + return ClassUtils.forName((String) attributeObject, null); + } + } + return Object.class; + } + private Class getDirectFactoryBeanGeneric( ConfigurableListableBeanFactory beanFactory, BeanDefinition definition, String name) throws ClassNotFoundException, LinkageError { @@ -129,9 +143,8 @@ abstract class BeanTypeRegistry { beanFactory.getBeanClassLoader()); Class generic = ResolvableType.forClass(factoryBeanClass) .as(FactoryBean.class).resolveGeneric(); - if ((generic == null || generic.equals(Object.class)) - && definition.hasAttribute(FACTORY_BEAN_OBJECT_TYPE)) { - generic = (Class) definition.getAttribute(FACTORY_BEAN_OBJECT_TYPE); + if (generic == null || generic.equals(Object.class)) { + generic = determineTypeFromDefinitionAttribute(definition); } return generic; } 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 80ef06f9a71..507c2549aa5 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2015 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. @@ -43,6 +43,7 @@ import static org.junit.Assert.assertTrue; * @author Dave Syer * @author Phillip Webb * @author Jakub Kubrynski + * @author Andy Wilkinson */ @SuppressWarnings("resource") public class ConditionalOnMissingBeanTests { @@ -157,8 +158,18 @@ public class ConditionalOnMissingBeanTests { } @Test - public void testOnMissingBeanConditionWithNonspecificFactoryBean() { - this.context.register(NonspecificFactoryBeanConfiguration.class, + public void testOnMissingBeanConditionWithNonspecificFactoryBeanWithClassAttribute() { + this.context.register(NonspecificFactoryBeanClassAttributeConfiguration.class, + ConditionalOnFactoryBean.class, + PropertyPlaceholderAutoConfiguration.class); + this.context.refresh(); + assertThat(this.context.getBean(ExampleBean.class).toString(), + equalTo("fromFactory")); + } + + @Test + public void testOnMissingBeanConditionWithNonspecificFactoryBeanWithStringAttribute() { + this.context.register(NonspecificFactoryBeanStringAttributeConfiguration.class, ConditionalOnFactoryBean.class, PropertyPlaceholderAutoConfiguration.class); this.context.refresh(); @@ -211,11 +222,11 @@ public class ConditionalOnMissingBeanTests { } @Configuration - @Import(NonspecificFactoryBeanRegistrar.class) - protected static class NonspecificFactoryBeanConfiguration { + @Import(NonspecificFactoryBeanClassAttributeRegistrar.class) + protected static class NonspecificFactoryBeanClassAttributeConfiguration { } - protected static class NonspecificFactoryBeanRegistrar implements + protected static class NonspecificFactoryBeanClassAttributeRegistrar implements ImportBeanDefinitionRegistrar { @Override @@ -232,6 +243,29 @@ public class ConditionalOnMissingBeanTests { } + @Configuration + @Import(NonspecificFactoryBeanClassAttributeRegistrar.class) + protected static class NonspecificFactoryBeanStringAttributeConfiguration { + } + + protected static class NonspecificFactoryBeanStringAttributeRegistrar implements + ImportBeanDefinitionRegistrar { + + @Override + public void registerBeanDefinitions(AnnotationMetadata meta, + BeanDefinitionRegistry registry) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder + .genericBeanDefinition(NonspecificFactoryBean.class); + builder.addConstructorArgValue("foo"); + builder.getBeanDefinition() + .setAttribute(OnBeanCondition.FACTORY_BEAN_OBJECT_TYPE, + ExampleBean.class.getName()); + registry.registerBeanDefinition("exampleBeanFactoryBean", + builder.getBeanDefinition()); + } + + } + @Configuration @Import(FactoryBeanRegistrar.class) protected static class RegisteredFactoryBeanConfiguration {