Skip to content

Commit 337673b

Browse files
committed
Support String values for factoryBeanObjectType attribute on bean def
To allow us to determine the type that Spring Integration’s GatewayProxyFactoryBean will create, the bean definition created by MessagingGatewayRegistrar needs to set the factoryBeanObjectType attribute. The current implementation of BeanTypeRegistry requires the attribute’s value to be a Class, however this would require Spring Integration’s namespace handler to load the class and class loading should be avoided in namespace handlers. This commit updates BeanTypeRegistry so that it supports both Class and String values for the factoryBeanObjectType. If the value is a String it will interpret it as a class name and attempt to load it. See gh-2811
1 parent ebb8d0c commit 337673b

File tree

2 files changed

+59
-12
lines changed

2 files changed

+59
-12
lines changed

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/BeanTypeRegistry.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
* </ul>
5555
*
5656
* @author Phillip Webb
57+
* @author Andy Wilkinson
5758
* @since 1.2.0
5859
*/
5960
abstract class BeanTypeRegistry {
@@ -115,23 +116,35 @@ private Class<?> getConfigurationClassFactoryBeanGeneric(
115116
definition.getFactoryMethodName());
116117
Class<?> generic = ResolvableType.forMethodReturnType(method)
117118
.as(FactoryBean.class).resolveGeneric();
118-
if ((generic == null || generic.equals(Object.class))
119-
&& definition.hasAttribute(FACTORY_BEAN_OBJECT_TYPE)) {
120-
generic = (Class<?>) definition.getAttribute(FACTORY_BEAN_OBJECT_TYPE);
119+
if (generic == null || generic.equals(Object.class)) {
120+
generic = determineTypeFromDefinitionAttribute(factoryDefinition);
121121
}
122122
return generic;
123123
}
124124

125+
private Class<?> determineTypeFromDefinitionAttribute(BeanDefinition definition)
126+
throws ClassNotFoundException, LinkageError {
127+
if (definition.hasAttribute(FACTORY_BEAN_OBJECT_TYPE)) {
128+
Object attributeObject = definition.getAttribute(FACTORY_BEAN_OBJECT_TYPE);
129+
if (attributeObject instanceof Class<?>) {
130+
return (Class<?>) attributeObject;
131+
}
132+
else if (attributeObject instanceof String) {
133+
return ClassUtils.forName((String) attributeObject, null);
134+
}
135+
}
136+
return Object.class;
137+
}
138+
125139
private Class<?> getDirectFactoryBeanGeneric(
126140
ConfigurableListableBeanFactory beanFactory, BeanDefinition definition,
127141
String name) throws ClassNotFoundException, LinkageError {
128142
Class<?> factoryBeanClass = ClassUtils.forName(definition.getBeanClassName(),
129143
beanFactory.getBeanClassLoader());
130144
Class<?> generic = ResolvableType.forClass(factoryBeanClass)
131145
.as(FactoryBean.class).resolveGeneric();
132-
if ((generic == null || generic.equals(Object.class))
133-
&& definition.hasAttribute(FACTORY_BEAN_OBJECT_TYPE)) {
134-
generic = (Class<?>) definition.getAttribute(FACTORY_BEAN_OBJECT_TYPE);
146+
if (generic == null || generic.equals(Object.class)) {
147+
generic = determineTypeFromDefinitionAttribute(definition);
135148
}
136149
return generic;
137150
}

spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBeanTests.java

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2013 the original author or authors.
2+
* Copyright 2012-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@
4343
* @author Dave Syer
4444
* @author Phillip Webb
4545
* @author Jakub Kubrynski
46+
* @author Andy Wilkinson
4647
*/
4748
@SuppressWarnings("resource")
4849
public class ConditionalOnMissingBeanTests {
@@ -157,8 +158,18 @@ public void testOnMissingBeanConditionWithRegisteredFactoryBean() {
157158
}
158159

159160
@Test
160-
public void testOnMissingBeanConditionWithNonspecificFactoryBean() {
161-
this.context.register(NonspecificFactoryBeanConfiguration.class,
161+
public void testOnMissingBeanConditionWithNonspecificFactoryBeanWithClassAttribute() {
162+
this.context.register(NonspecificFactoryBeanClassAttributeConfiguration.class,
163+
ConditionalOnFactoryBean.class,
164+
PropertyPlaceholderAutoConfiguration.class);
165+
this.context.refresh();
166+
assertThat(this.context.getBean(ExampleBean.class).toString(),
167+
equalTo("fromFactory"));
168+
}
169+
170+
@Test
171+
public void testOnMissingBeanConditionWithNonspecificFactoryBeanWithStringAttribute() {
172+
this.context.register(NonspecificFactoryBeanStringAttributeConfiguration.class,
162173
ConditionalOnFactoryBean.class,
163174
PropertyPlaceholderAutoConfiguration.class);
164175
this.context.refresh();
@@ -211,11 +222,11 @@ public FactoryBean exampleBeanFactoryBean() {
211222
}
212223

213224
@Configuration
214-
@Import(NonspecificFactoryBeanRegistrar.class)
215-
protected static class NonspecificFactoryBeanConfiguration {
225+
@Import(NonspecificFactoryBeanClassAttributeRegistrar.class)
226+
protected static class NonspecificFactoryBeanClassAttributeConfiguration {
216227
}
217228

218-
protected static class NonspecificFactoryBeanRegistrar implements
229+
protected static class NonspecificFactoryBeanClassAttributeRegistrar implements
219230
ImportBeanDefinitionRegistrar {
220231

221232
@Override
@@ -232,6 +243,29 @@ public void registerBeanDefinitions(AnnotationMetadata meta,
232243

233244
}
234245

246+
@Configuration
247+
@Import(NonspecificFactoryBeanClassAttributeRegistrar.class)
248+
protected static class NonspecificFactoryBeanStringAttributeConfiguration {
249+
}
250+
251+
protected static class NonspecificFactoryBeanStringAttributeRegistrar implements
252+
ImportBeanDefinitionRegistrar {
253+
254+
@Override
255+
public void registerBeanDefinitions(AnnotationMetadata meta,
256+
BeanDefinitionRegistry registry) {
257+
BeanDefinitionBuilder builder = BeanDefinitionBuilder
258+
.genericBeanDefinition(NonspecificFactoryBean.class);
259+
builder.addConstructorArgValue("foo");
260+
builder.getBeanDefinition()
261+
.setAttribute(OnBeanCondition.FACTORY_BEAN_OBJECT_TYPE,
262+
ExampleBean.class.getName());
263+
registry.registerBeanDefinition("exampleBeanFactoryBean",
264+
builder.getBeanDefinition());
265+
}
266+
267+
}
268+
235269
@Configuration
236270
@Import(FactoryBeanRegistrar.class)
237271
protected static class RegisteredFactoryBeanConfiguration {

0 commit comments

Comments
 (0)