Skip to content

Commit 3185f67

Browse files
committed
Avoid stack overflow in case of chained factory-bean references to FactoryBean class
Issue: SPR-14551
1 parent 9520a59 commit 3185f67

File tree

4 files changed

+28
-26
lines changed

4 files changed

+28
-26
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2016 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.
@@ -114,6 +114,7 @@ public interface BeanFactory {
114114
*/
115115
String FACTORY_BEAN_PREFIX = "&";
116116

117+
117118
/**
118119
* Return an instance, which may be shared or independent, of the specified bean.
119120
* <p>This method allows a Spring BeanFactory to be used as a replacement for the
@@ -151,15 +152,16 @@ public interface BeanFactory {
151152

152153
/**
153154
* Return the bean instance that uniquely matches the given object type, if any.
154-
* @param requiredType type the bean must match; can be an interface or superclass.
155-
* {@code null} is disallowed.
156155
* <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
157156
* but may also be translated into a conventional by-name lookup based on the name
158157
* of the given type. For more extensive retrieval operations across sets of beans,
159158
* use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
159+
* @param requiredType type the bean must match; can be an interface or superclass.
160+
* {@code null} is disallowed.
160161
* @return an instance of the single bean matching the required type
161162
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
162163
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
164+
* @throws BeansException if the bean could not be created
163165
* @since 3.0
164166
* @see ListableBeanFactory
165167
*/
@@ -170,7 +172,7 @@ public interface BeanFactory {
170172
* <p>Allows for specifying explicit constructor arguments / factory method arguments,
171173
* overriding the specified default arguments (if any) in the bean definition.
172174
* @param name the name of the bean to retrieve
173-
* @param args arguments to use if creating a prototype using explicit arguments
175+
* @param args arguments to use when creating a prototype using explicit arguments
174176
* @return an instance of the bean
175177
* @throws NoSuchBeanDefinitionException if there is no such bean definition
176178
* @throws BeanDefinitionStoreException if arguments have been given but

spring-beans/src/main/java/org/springframework/beans/factory/NamedBean.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2006 the original author or authors.
2+
* Copyright 2002-2016 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.
@@ -17,10 +17,10 @@
1717
package org.springframework.beans.factory;
1818

1919
/**
20-
* Counterpart of BeanNameAware. Returns the bean name of an object.
20+
* Counterpart of {@link BeanNameAware}. Returns the bean name of an object.
2121
*
22-
* <p>This interface can be introduced to avoid a brittle dependence
23-
* on bean name in objects used with Spring IoC and Spring AOP.
22+
* <p>This interface can be introduced to avoid a brittle dependence on
23+
* bean name in objects used with Spring IoC and Spring AOP.
2424
*
2525
* @author Rod Johnson
2626
* @since 2.0
@@ -29,7 +29,7 @@
2929
public interface NamedBean {
3030

3131
/**
32-
* Return the name of this bean in a Spring bean factory.
32+
* Return the name of this bean in a Spring bean factory, if known.
3333
*/
3434
String getBeanName();
3535

spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2016 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.
@@ -114,9 +114,9 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
114114
* <p>Performs full initialization of the bean, including all applicable
115115
* {@link BeanPostProcessor BeanPostProcessors}.
116116
* <p>Note: This is intended for creating a fresh instance, populating annotated
117-
* fields and methods as well as applying all standard bean initialiation callbacks.
117+
* fields and methods as well as applying all standard bean initialization callbacks.
118118
* It does <i>not</> imply traditional by-name or by-type autowiring of properties;
119-
* use {@link #createBean(Class, int, boolean)} for that purposes.
119+
* use {@link #createBean(Class, int, boolean)} for those purposes.
120120
* @param beanClass the class of the bean to create
121121
* @return the new bean instance
122122
* @throws BeansException if instantiation or wiring failed
@@ -129,7 +129,7 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
129129
* <p>Note: This is essentially intended for (re-)populating annotated fields and
130130
* methods, either for new instances or for deserialized instances. It does
131131
* <i>not</i> imply traditional by-name or by-type autowiring of properties;
132-
* use {@link #autowireBeanProperties} for that purposes.
132+
* use {@link #autowireBeanProperties} for those purposes.
133133
* @param existingBean the existing bean instance
134134
* @throws BeansException if wiring failed
135135
*/

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2016 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.
@@ -425,9 +425,7 @@ public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, St
425425
* @see #doCreateBean
426426
*/
427427
@Override
428-
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
429-
throws BeanCreationException {
430-
428+
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
431429
if (logger.isDebugEnabled()) {
432430
logger.debug("Creating instance of bean '" + beanName + "'");
433431
}
@@ -596,7 +594,7 @@ protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Clas
596594
}
597595

598596
/**
599-
* Determine the bean type for the given bean definition which is based on
597+
* Determine the target type for the given bean definition which is based on
600598
* a factory method. Only called if there is no singleton instance registered
601599
* for the target bean already.
602600
* <p>This implementation determines the type matching {@link #createBean}'s
@@ -606,7 +604,7 @@ protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Clas
606604
* @param mbd the merged bean definition for the bean
607605
* @param typesToMatch the types to match in case of internal type matching purposes
608606
* (also signals that the returned {@code Class} will never be exposed to application code)
609-
* @return the type for the bean if determinable, or {@code null} else
607+
* @return the type for the bean if determinable, or {@code null} otherwise
610608
* @see #createBean
611609
*/
612610
protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
@@ -745,10 +743,14 @@ public void doWith(Method method) throws IllegalArgumentException, IllegalAccess
745743
if (objectType.value != null) {
746744
return objectType.value;
747745
}
746+
else {
747+
// No type found for shortcut FactoryBean instance:
748+
// fall back to full creation of the FactoryBean instance.
749+
return super.getTypeForFactoryBean(beanName, mbd);
750+
}
748751
}
749752

750-
// No type found - fall back to full creation of the FactoryBean instance.
751-
return super.getTypeForFactoryBean(beanName, mbd);
753+
return null;
752754
}
753755

754756
/**
@@ -767,7 +769,7 @@ protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd,
767769
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
768770
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
769771
if (exposedObject == null) {
770-
return exposedObject;
772+
return null;
771773
}
772774
}
773775
}
@@ -782,8 +784,7 @@ protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd,
782784

783785
/**
784786
* Obtain a "shortcut" singleton FactoryBean instance to use for a
785-
* {@code getObjectType()} call, without full initialization
786-
* of the FactoryBean.
787+
* {@code getObjectType()} call, without full initialization of the FactoryBean.
787788
* @param beanName the name of the bean
788789
* @param mbd the bean definition for the bean
789790
* @return the FactoryBean instance, or {@code null} to indicate
@@ -824,8 +825,7 @@ private FactoryBean<?> getSingletonFactoryBeanForTypeCheck(String beanName, Root
824825

825826
/**
826827
* Obtain a "shortcut" non-singleton FactoryBean instance to use for a
827-
* {@code getObjectType()} call, without full initialization
828-
* of the FactoryBean.
828+
* {@code getObjectType()} call, without full initialization of the FactoryBean.
829829
* @param beanName the name of the bean
830830
* @param mbd the bean definition for the bean
831831
* @return the FactoryBean instance, or {@code null} to indicate

0 commit comments

Comments
 (0)