From 3185f67b43d3749fcfbcae5b3a0ed48c1df602d5 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 12 Aug 2016 00:02:03 +0200 Subject: [PATCH] Avoid stack overflow in case of chained factory-bean references to FactoryBean class Issue: SPR-14551 --- .../beans/factory/BeanFactory.java | 10 ++++--- .../beans/factory/NamedBean.java | 10 +++---- .../config/AutowireCapableBeanFactory.java | 8 +++--- .../AbstractAutowireCapableBeanFactory.java | 26 +++++++++---------- 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java index 7d65a3aaf41..00191904e2a 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -114,6 +114,7 @@ public interface BeanFactory { */ String FACTORY_BEAN_PREFIX = "&"; + /** * Return an instance, which may be shared or independent, of the specified bean. *

This method allows a Spring BeanFactory to be used as a replacement for the @@ -151,15 +152,16 @@ public interface BeanFactory { /** * Return the bean instance that uniquely matches the given object type, if any. - * @param requiredType type the bean must match; can be an interface or superclass. - * {@code null} is disallowed. *

This method goes into {@link ListableBeanFactory} by-type lookup territory * but may also be translated into a conventional by-name lookup based on the name * of the given type. For more extensive retrieval operations across sets of beans, * use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}. + * @param requiredType type the bean must match; can be an interface or superclass. + * {@code null} is disallowed. * @return an instance of the single bean matching the required type * @throws NoSuchBeanDefinitionException if no bean of the given type was found * @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found + * @throws BeansException if the bean could not be created * @since 3.0 * @see ListableBeanFactory */ @@ -170,7 +172,7 @@ public interface BeanFactory { *

Allows for specifying explicit constructor arguments / factory method arguments, * overriding the specified default arguments (if any) in the bean definition. * @param name the name of the bean to retrieve - * @param args arguments to use if creating a prototype using explicit arguments + * @param args arguments to use when creating a prototype using explicit arguments * @return an instance of the bean * @throws NoSuchBeanDefinitionException if there is no such bean definition * @throws BeanDefinitionStoreException if arguments have been given but diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/NamedBean.java b/spring-beans/src/main/java/org/springframework/beans/factory/NamedBean.java index e1e5ed33f57..9f2453ff653 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/NamedBean.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/NamedBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2006 the original author or authors. + * Copyright 2002-2016 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. @@ -17,10 +17,10 @@ package org.springframework.beans.factory; /** - * Counterpart of BeanNameAware. Returns the bean name of an object. + * Counterpart of {@link BeanNameAware}. Returns the bean name of an object. * - *

This interface can be introduced to avoid a brittle dependence - * on bean name in objects used with Spring IoC and Spring AOP. + *

This interface can be introduced to avoid a brittle dependence on + * bean name in objects used with Spring IoC and Spring AOP. * * @author Rod Johnson * @since 2.0 @@ -29,7 +29,7 @@ package org.springframework.beans.factory; public interface NamedBean { /** - * Return the name of this bean in a Spring bean factory. + * Return the name of this bean in a Spring bean factory, if known. */ String getBeanName(); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java index e1cdd1cac22..9cf2e3d5ebe 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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. @@ -114,9 +114,9 @@ public interface AutowireCapableBeanFactory extends BeanFactory { *

Performs full initialization of the bean, including all applicable * {@link BeanPostProcessor BeanPostProcessors}. *

Note: This is intended for creating a fresh instance, populating annotated - * fields and methods as well as applying all standard bean initialiation callbacks. + * fields and methods as well as applying all standard bean initialization callbacks. * It does not imply traditional by-name or by-type autowiring of properties; - * use {@link #createBean(Class, int, boolean)} for that purposes. + * use {@link #createBean(Class, int, boolean)} for those purposes. * @param beanClass the class of the bean to create * @return the new bean instance * @throws BeansException if instantiation or wiring failed @@ -129,7 +129,7 @@ public interface AutowireCapableBeanFactory extends BeanFactory { *

Note: This is essentially intended for (re-)populating annotated fields and * methods, either for new instances or for deserialized instances. It does * not imply traditional by-name or by-type autowiring of properties; - * use {@link #autowireBeanProperties} for that purposes. + * use {@link #autowireBeanProperties} for those purposes. * @param existingBean the existing bean instance * @throws BeansException if wiring failed */ diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index f1bbf0325c1..651af574da4 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -425,9 +425,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * @see #doCreateBean */ @Override - protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) - throws BeanCreationException { - + protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } @@ -596,7 +594,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac } /** - * Determine the bean type for the given bean definition which is based on + * Determine the target type for the given bean definition which is based on * a factory method. Only called if there is no singleton instance registered * for the target bean already. *

This implementation determines the type matching {@link #createBean}'s @@ -606,7 +604,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * @param mbd the merged bean definition for the bean * @param typesToMatch the types to match in case of internal type matching purposes * (also signals that the returned {@code Class} will never be exposed to application code) - * @return the type for the bean if determinable, or {@code null} else + * @return the type for the bean if determinable, or {@code null} otherwise * @see #createBean */ protected Class getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) { @@ -745,10 +743,14 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac if (objectType.value != null) { return objectType.value; } + else { + // No type found for shortcut FactoryBean instance: + // fall back to full creation of the FactoryBean instance. + return super.getTypeForFactoryBean(beanName, mbd); + } } - // No type found - fall back to full creation of the FactoryBean instance. - return super.getTypeForFactoryBean(beanName, mbd); + return null; } /** @@ -767,7 +769,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); if (exposedObject == null) { - return exposedObject; + return null; } } } @@ -782,8 +784,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac /** * Obtain a "shortcut" singleton FactoryBean instance to use for a - * {@code getObjectType()} call, without full initialization - * of the FactoryBean. + * {@code getObjectType()} call, without full initialization of the FactoryBean. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @return the FactoryBean instance, or {@code null} to indicate @@ -824,8 +825,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac /** * Obtain a "shortcut" non-singleton FactoryBean instance to use for a - * {@code getObjectType()} call, without full initialization - * of the FactoryBean. + * {@code getObjectType()} call, without full initialization of the FactoryBean. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @return the FactoryBean instance, or {@code null} to indicate