summaryrefslogtreecommitdiff
path: root/spring-beans/src/main/java/org/springframework/beans/factory/support
diff options
context:
space:
mode:
authorEmmanuel Bourg <ebourg@apache.org>2016-12-23 09:09:27 +0100
committerEmmanuel Bourg <ebourg@apache.org>2016-12-23 09:09:27 +0100
commit7b2b01514e9875ddcb0f6cc15c6557a0417b22fc (patch)
tree9327f61a75d4bb1bcac2e8827d315d9a37c201a7 /spring-beans/src/main/java/org/springframework/beans/factory/support
parent0591d269b8b2b33af090ace1ecbd408490618428 (diff)
New upstream version 4.3.5
Diffstat (limited to 'spring-beans/src/main/java/org/springframework/beans/factory/support')
-rw-r--r--spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java32
-rw-r--r--spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java30
-rw-r--r--spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java12
-rw-r--r--spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionReaderUtils.java35
-rw-r--r--spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java52
-rw-r--r--spring-beans/src/main/java/org/springframework/beans/factory/support/GenericTypeAwareAutowireCandidateResolver.java27
-rw-r--r--spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java2
-rw-r--r--spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java8
8 files changed, 120 insertions, 78 deletions
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 69b3d93a..1884912e 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
@@ -74,6 +74,7 @@ import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.PriorityOrdered;
+import org.springframework.core.ResolvableType;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
@@ -659,9 +660,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
* @see #createBean
*/
protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
- Class<?> preResolved = mbd.resolvedFactoryMethodReturnType;
- if (preResolved != null) {
- return preResolved;
+ ResolvableType cachedReturnType = mbd.factoryMethodReturnType;
+ if (cachedReturnType != null) {
+ return cachedReturnType.resolve();
}
Class<?> factoryClass;
@@ -685,11 +686,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
if (factoryClass == null) {
return null;
}
+ factoryClass = ClassUtils.getUserClass(factoryClass);
// If all factory methods have the same return type, return that type.
// Can't clearly figure out exact method due to type converting / autowiring!
Class<?> commonType = null;
- boolean cache = false;
+ Method uniqueCandidate = null;
int minNrOfArgs = mbd.getConstructorArgumentValues().getArgumentCount();
Method[] candidates = ReflectionUtils.getUniqueDeclaredMethods(factoryClass);
for (Method factoryMethod : candidates) {
@@ -724,8 +726,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
Class<?> returnType = AutowireUtils.resolveReturnTypeForFactoryMethod(
factoryMethod, args, getBeanClassLoader());
if (returnType != null) {
- cache = true;
+ uniqueCandidate = (commonType == null ? factoryMethod : null);
commonType = ClassUtils.determineCommonAncestor(returnType, commonType);
+ if (commonType == null) {
+ // Ambiguous return types found: return null to indicate "not determinable".
+ return null;
+ }
}
}
catch (Throwable ex) {
@@ -735,22 +741,22 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
}
else {
+ uniqueCandidate = (commonType == null ? factoryMethod : null);
commonType = ClassUtils.determineCommonAncestor(factoryMethod.getReturnType(), commonType);
+ if (commonType == null) {
+ // Ambiguous return types found: return null to indicate "not determinable".
+ return null;
+ }
}
}
}
if (commonType != null) {
// Clear return type found: all factory methods return same type.
- if (cache) {
- mbd.resolvedFactoryMethodReturnType = commonType;
- }
- return commonType;
- }
- else {
- // Ambiguous return types found: return null to indicate "not determinable".
- return null;
+ mbd.factoryMethodReturnType = (uniqueCandidate != null ?
+ ResolvableType.forMethodReturnType(uniqueCandidate) : ResolvableType.forClass(commonType));
}
+ return commonType;
}
/**
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
index 104d91c1..326c3295 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
@@ -134,13 +134,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
private final Set<PropertyEditorRegistrar> propertyEditorRegistrars =
new LinkedHashSet<PropertyEditorRegistrar>(4);
- /** A custom TypeConverter to use, overriding the default PropertyEditor mechanism */
- private TypeConverter typeConverter;
-
/** Custom PropertyEditors to apply to the beans of this factory */
private final Map<Class<?>, Class<? extends PropertyEditor>> customEditors =
new HashMap<Class<?>, Class<? extends PropertyEditor>>(4);
+ /** A custom TypeConverter to use, overriding the default PropertyEditor mechanism */
+ private TypeConverter typeConverter;
+
/** String resolvers to apply e.g. to annotation attribute values */
private final List<StringValueResolver> embeddedValueResolvers = new LinkedList<StringValueResolver>();
@@ -517,7 +517,10 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
// Retrieve corresponding bean definition.
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
- Class<?> classToMatch = typeToMatch.getRawClass();
+ Class<?> classToMatch = typeToMatch.resolve();
+ if (classToMatch == null) {
+ classToMatch = FactoryBean.class;
+ }
Class<?>[] typesToMatch = (FactoryBean.class == classToMatch ?
new Class<?>[] {classToMatch} : new Class<?>[] {FactoryBean.class, classToMatch});
@@ -557,6 +560,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
}
}
+ ResolvableType resolvableType = mbd.targetType;
+ if (resolvableType == null) {
+ resolvableType = mbd.factoryMethodReturnType;
+ }
+ if (resolvableType != null && resolvableType.resolve() == beanType) {
+ return typeToMatch.isAssignableFrom(resolvableType);
+ }
return typeToMatch.isAssignableFrom(beanType);
}
}
@@ -921,10 +931,12 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
setBeanClassLoader(otherFactory.getBeanClassLoader());
setCacheBeanMetadata(otherFactory.isCacheBeanMetadata());
setBeanExpressionResolver(otherFactory.getBeanExpressionResolver());
+ setConversionService(otherFactory.getConversionService());
if (otherFactory instanceof AbstractBeanFactory) {
AbstractBeanFactory otherAbstractFactory = (AbstractBeanFactory) otherFactory;
- this.customEditors.putAll(otherAbstractFactory.customEditors);
this.propertyEditorRegistrars.addAll(otherAbstractFactory.propertyEditorRegistrars);
+ this.customEditors.putAll(otherAbstractFactory.customEditors);
+ this.typeConverter = otherAbstractFactory.typeConverter;
this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors);
this.hasInstantiationAwareBeanPostProcessors = this.hasInstantiationAwareBeanPostProcessors ||
otherAbstractFactory.hasInstantiationAwareBeanPostProcessors;
@@ -935,6 +947,10 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
}
else {
setTypeConverter(otherFactory.getTypeConverter());
+ String[] otherScopeNames = otherFactory.getRegisteredScopeNames();
+ for (String scopeName : otherScopeNames) {
+ this.scopes.put(scopeName, otherFactory.getRegisteredScope(scopeName));
+ }
}
}
@@ -1441,6 +1457,10 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* @return the type of the bean, or {@code null} if not predictable
*/
protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
+ Class<?> targetType = mbd.getTargetType();
+ if (targetType != null) {
+ return targetType;
+ }
if (mbd.getFactoryMethodName() != null) {
return null;
}
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java
index 1bf54034..0b650df8 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.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.
@@ -162,8 +162,8 @@ abstract class AutowireUtils {
* Determine the target type for the generic return type of the given
* <em>generic factory method</em>, where formal type variables are declared
* on the given method itself.
- * <p>For example, given a factory method with the following signature,
- * if {@code resolveReturnTypeForFactoryMethod()} is invoked with the reflected
+ * <p>For example, given a factory method with the following signature, if
+ * {@code resolveReturnTypeForFactoryMethod()} is invoked with the reflected
* method for {@code creatProxy()} and an {@code Object[]} array containing
* {@code MyService.class}, {@code resolveReturnTypeForFactoryMethod()} will
* infer that the target return type is {@code MyService}.
@@ -184,9 +184,9 @@ abstract class AutowireUtils {
* @param method the method to introspect (never {@code null})
* @param args the arguments that will be supplied to the method when it is
* invoked (never {@code null})
- * @param classLoader the ClassLoader to resolve class names against, if necessary
- * (never {@code null})
- * @return the resolved target return type, the standard return type, or {@code null}
+ * @param classLoader the ClassLoader to resolve class names against,
+ * if necessary (never {@code null})
+ * @return the resolved target return type or the standard method return type
* @since 3.2.5
*/
public static Class<?> resolveReturnTypeForFactoryMethod(Method method, Object[] args, ClassLoader classLoader) {
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionReaderUtils.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionReaderUtils.java
index f56f0e52..8a745dab 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionReaderUtils.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionReaderUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 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.
@@ -70,6 +70,23 @@ public class BeanDefinitionReaderUtils {
}
/**
+ * Generate a bean name for the given top-level bean definition,
+ * unique within the given bean factory.
+ * @param beanDefinition the bean definition to generate a bean name for
+ * @param registry the bean factory that the definition is going to be
+ * registered with (to check for existing bean names)
+ * @return the generated bean name
+ * @throws BeanDefinitionStoreException if no unique name can be generated
+ * for the given bean definition
+ * @see #generateBeanName(BeanDefinition, BeanDefinitionRegistry, boolean)
+ */
+ public static String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry registry)
+ throws BeanDefinitionStoreException {
+
+ return generateBeanName(beanDefinition, registry, false);
+ }
+
+ /**
* Generate a bean name for the given bean definition, unique within the
* given bean factory.
* @param definition the bean definition to generate a bean name for
@@ -118,22 +135,6 @@ public class BeanDefinitionReaderUtils {
}
/**
- * Generate a bean name for the given top-level bean definition,
- * unique within the given bean factory.
- * @param beanDefinition the bean definition to generate a bean name for
- * @param registry the bean factory that the definition is going to be
- * registered with (to check for existing bean names)
- * @return the generated bean name
- * @throws BeanDefinitionStoreException if no unique name can be generated
- * for the given bean definition
- */
- public static String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry registry)
- throws BeanDefinitionStoreException {
-
- return generateBeanName(beanDefinition, registry, false);
- }
-
- /**
* Register the given bean definition with the given bean factory.
* @param definitionHolder the bean definition including name and aliases
* @param registry the bean factory to register with
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
index c85ef3ca..83448499 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
@@ -43,6 +43,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Provider;
+import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanCreationException;
@@ -266,6 +267,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
/**
* Set a {@link java.util.Comparator} for dependency Lists and arrays.
+ * @since 4.0
* @see org.springframework.core.OrderComparator
* @see org.springframework.core.annotation.AnnotationAwareOrderComparator
*/
@@ -275,6 +277,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
/**
* Return the dependency comparator for this BeanFactory (may be {@code null}.
+ * @since 4.0
*/
public Comparator<Object> getDependencyComparator() {
return this.dependencyComparator;
@@ -289,11 +292,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
if (autowireCandidateResolver instanceof BeanFactoryAware) {
if (System.getSecurityManager() != null) {
- final BeanFactory target = this;
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
- ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(target);
+ ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(DefaultListableBeanFactory.this);
return null;
}
}, getAccessControlContext());
@@ -320,7 +322,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
DefaultListableBeanFactory otherListableFactory = (DefaultListableBeanFactory) otherFactory;
this.allowBeanDefinitionOverriding = otherListableFactory.allowBeanDefinitionOverriding;
this.allowEagerClassLoading = otherListableFactory.allowEagerClassLoading;
- this.autowireCandidateResolver = otherListableFactory.autowireCandidateResolver;
+ this.dependencyComparator = otherListableFactory.dependencyComparator;
+ // A clone of the AutowireCandidateResolver since it is potentially BeanFactoryAware...
+ setAutowireCandidateResolver(BeanUtils.instantiateClass(getAutowireCandidateResolver().getClass()));
+ // Make resolvable dependencies (e.g. ResourceLoader) available here as well...
this.resolvableDependencies.putAll(otherListableFactory.resolvableDependencies);
}
}
@@ -367,7 +372,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Override
public String[] getBeanDefinitionNames() {
if (this.frozenBeanDefinitionNames != null) {
- return this.frozenBeanDefinitionNames;
+ return this.frozenBeanDefinitionNames.clone();
}
else {
return StringUtils.toStringArray(this.beanDefinitionNames);
@@ -1142,7 +1147,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (type.isArray()) {
Class<?> componentType = type.getComponentType();
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
- new MultiElementDependencyDescriptor(descriptor));
+ new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
@@ -1162,7 +1167,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
- new MultiElementDependencyDescriptor(descriptor));
+ new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
@@ -1186,7 +1191,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
- new MultiElementDependencyDescriptor(descriptor));
+ new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
@@ -1253,24 +1258,27 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
}
}
- for (String candidateName : candidateNames) {
- if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {
- addCandidateEntry(result, candidateName, descriptor, requiredType);
+ for (String candidate : candidateNames) {
+ if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
+ addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
// Consider fallback matches if the first pass failed to find anything...
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
- for (String candidateName : candidateNames) {
- if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
- addCandidateEntry(result, candidateName, descriptor, requiredType);
+ for (String candidate : candidateNames) {
+ if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {
+ addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty()) {
- // Consider self references before as a final pass
- for (String candidateName : candidateNames) {
- if (isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
- addCandidateEntry(result, candidateName, descriptor, requiredType);
+ // Consider self references as a final pass...
+ // but in the case of a dependency collection, not the very same bean itself.
+ for (String candidate : candidateNames) {
+ if (isSelfReference(beanName, candidate) &&
+ (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
+ isAutowireCandidate(candidate, fallbackDescriptor)) {
+ addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
@@ -1285,7 +1293,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
DependencyDescriptor descriptor, Class<?> requiredType) {
- if (descriptor instanceof MultiElementDependencyDescriptor || containsSingleton(candidateName)) {
+ if (descriptor instanceof MultiElementDescriptor || containsSingleton(candidateName)) {
candidates.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
}
else {
@@ -1476,10 +1484,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
Class<?> targetType = mbd.getTargetType();
if (targetType != null && type.isAssignableFrom(targetType) &&
isAutowireCandidate(beanName, mbd, descriptor, getAutowireCandidateResolver())) {
- // Probably a poxy interfering with target type match -> throw meaningful exception.
+ // Probably a proxy interfering with target type match -> throw meaningful exception.
Object beanInstance = getSingleton(beanName, false);
Class<?> beanType = (beanInstance != null ? beanInstance.getClass() : predictBeanType(beanName, mbd));
- if (type != beanType) {
+ if (!type.isAssignableFrom((beanType))) {
throw new BeanNotOfRequiredTypeException(beanName, type, beanType);
}
}
@@ -1739,9 +1747,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
- private static class MultiElementDependencyDescriptor extends NestedDependencyDescriptor {
+ private static class MultiElementDescriptor extends NestedDependencyDescriptor {
- public MultiElementDependencyDescriptor(DependencyDescriptor original) {
+ public MultiElementDescriptor(DependencyDescriptor original) {
super(original);
}
}
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericTypeAwareAutowireCandidateResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericTypeAwareAutowireCandidateResolver.java
index cba9e977..b204d551 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericTypeAwareAutowireCandidateResolver.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericTypeAwareAutowireCandidateResolver.java
@@ -147,22 +147,23 @@ public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandid
protected ResolvableType getReturnTypeForFactoryMethod(RootBeanDefinition rbd, DependencyDescriptor descriptor) {
// Should typically be set for any kind of factory method, since the BeanFactory
// pre-resolves them before reaching out to the AutowireCandidateResolver...
- Class<?> preResolved = rbd.resolvedFactoryMethodReturnType;
- if (preResolved != null) {
- return ResolvableType.forClass(preResolved);
+ ResolvableType returnType = rbd.factoryMethodReturnType;
+ if (returnType == null) {
+ Method factoryMethod = rbd.getResolvedFactoryMethod();
+ if (factoryMethod != null) {
+ returnType = ResolvableType.forMethodReturnType(factoryMethod);
+ }
}
- else {
- Method resolvedFactoryMethod = rbd.getResolvedFactoryMethod();
- if (resolvedFactoryMethod != null) {
- if (descriptor.getDependencyType().isAssignableFrom(resolvedFactoryMethod.getReturnType())) {
- // Only use factory method metadata if the return type is actually expressive enough
- // for our dependency. Otherwise, the returned instance type may have matched instead
- // in case of a singleton instance having been registered with the container already.
- return ResolvableType.forMethodReturnType(resolvedFactoryMethod);
- }
+ if (returnType != null) {
+ Class<?> resolvedClass = returnType.resolve();
+ if (resolvedClass != null && descriptor.getDependencyType().isAssignableFrom(resolvedClass)) {
+ // Only use factory method metadata if the return type is actually expressive enough
+ // for our dependency. Otherwise, the returned instance type may have matched instead
+ // in case of a singleton instance having been registered with the container already.
+ return returnType;
}
- return null;
}
+ return null;
}
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java
index 237e672a..6f61186a 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java
@@ -64,7 +64,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
volatile Class<?> resolvedTargetType;
/** Package-visible field for caching the return type of a generically typed factory method */
- volatile Class<?> resolvedFactoryMethodReturnType;
+ volatile ResolvableType factoryMethodReturnType;
/** Common lock for the four constructor fields below */
final Object constructorArgumentLock = new Object();
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
index 32866846..d1aa847f 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
@@ -248,7 +248,13 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
@Override
public String[] getBeanNamesForType(ResolvableType type) {
- boolean isFactoryType = (type != null && FactoryBean.class.isAssignableFrom(type.getRawClass()));
+ boolean isFactoryType = false;
+ if (type != null) {
+ Class<?> resolved = type.resolve();
+ if (resolved != null && FactoryBean.class.isAssignableFrom(resolved)) {
+ isFactoryType = true;
+ }
+ }
List<String> matches = new ArrayList<String>();
for (Map.Entry<String, Object> entry : this.beans.entrySet()) {
String name = entry.getKey();