Consistent type variable resolution for arrays/collections (in particular at field level)
Deprecating GenericCollectionTypeResolver in favor of direct ResolvableType usage.
Issue: SPR-15160
(cherry picked from commit 5e946c2)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -28,7 +28,6 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.InjectionPoint;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
@@ -63,6 +62,8 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
|
||||
private Class<?> containingClass;
|
||||
|
||||
private volatile ResolvableType resolvableType;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new descriptor for a method or constructor parameter.
|
||||
@@ -214,6 +215,7 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
*/
|
||||
public void increaseNestingLevel() {
|
||||
this.nestingLevel++;
|
||||
this.resolvableType = null;
|
||||
if (this.methodParameter != null) {
|
||||
this.methodParameter.increaseNestingLevel();
|
||||
}
|
||||
@@ -227,6 +229,7 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
*/
|
||||
public void setContainingClass(Class<?> containingClass) {
|
||||
this.containingClass = containingClass;
|
||||
this.resolvableType = null;
|
||||
if (this.methodParameter != null) {
|
||||
GenericTypeResolver.resolveParameterType(this.methodParameter, containingClass);
|
||||
}
|
||||
@@ -237,8 +240,12 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
* @since 4.0
|
||||
*/
|
||||
public ResolvableType getResolvableType() {
|
||||
return (this.field != null ? ResolvableType.forField(this.field, this.nestingLevel, this.containingClass) :
|
||||
ResolvableType.forMethodParameter(this.methodParameter));
|
||||
if (this.resolvableType == null) {
|
||||
this.resolvableType = (this.field != null ?
|
||||
ResolvableType.forField(this.field, this.nestingLevel, this.containingClass) :
|
||||
ResolvableType.forMethodParameter(this.methodParameter));
|
||||
}
|
||||
return this.resolvableType;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -324,31 +331,37 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
/**
|
||||
* Determine the generic element type of the wrapped Collection parameter/field, if any.
|
||||
* @return the generic type, or {@code null} if none
|
||||
* @deprecated as of 4.3.6, in favor of direct {@link ResolvableType} usage
|
||||
*/
|
||||
@Deprecated
|
||||
public Class<?> getCollectionType() {
|
||||
return (this.field != null ?
|
||||
GenericCollectionTypeResolver.getCollectionFieldType(this.field, this.nestingLevel) :
|
||||
GenericCollectionTypeResolver.getCollectionParameterType(this.methodParameter));
|
||||
org.springframework.core.GenericCollectionTypeResolver.getCollectionFieldType(this.field, this.nestingLevel) :
|
||||
org.springframework.core.GenericCollectionTypeResolver.getCollectionParameterType(this.methodParameter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the generic key type of the wrapped Map parameter/field, if any.
|
||||
* @return the generic type, or {@code null} if none
|
||||
* @deprecated as of 4.3.6, in favor of direct {@link ResolvableType} usage
|
||||
*/
|
||||
@Deprecated
|
||||
public Class<?> getMapKeyType() {
|
||||
return (this.field != null ?
|
||||
GenericCollectionTypeResolver.getMapKeyFieldType(this.field, this.nestingLevel) :
|
||||
GenericCollectionTypeResolver.getMapKeyParameterType(this.methodParameter));
|
||||
org.springframework.core.GenericCollectionTypeResolver.getMapKeyFieldType(this.field, this.nestingLevel) :
|
||||
org.springframework.core.GenericCollectionTypeResolver.getMapKeyParameterType(this.methodParameter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the generic value type of the wrapped Map parameter/field, if any.
|
||||
* @return the generic type, or {@code null} if none
|
||||
* @deprecated as of 4.3.6, in favor of direct {@link ResolvableType} usage
|
||||
*/
|
||||
@Deprecated
|
||||
public Class<?> getMapValueType() {
|
||||
return (this.field != null ?
|
||||
GenericCollectionTypeResolver.getMapValueFieldType(this.field, this.nestingLevel) :
|
||||
GenericCollectionTypeResolver.getMapValueParameterType(this.methodParameter));
|
||||
org.springframework.core.GenericCollectionTypeResolver.getMapValueFieldType(this.field, this.nestingLevel) :
|
||||
org.springframework.core.GenericCollectionTypeResolver.getMapValueParameterType(this.methodParameter));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -21,7 +21,7 @@ import java.util.List;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.ResolvableType;
|
||||
|
||||
/**
|
||||
* Simple factory for shared List instances. Allows for central setup
|
||||
@@ -86,7 +86,7 @@ public class ListFactoryBean extends AbstractFactoryBean<List<Object>> {
|
||||
}
|
||||
Class<?> valueType = null;
|
||||
if (this.targetListClass != null) {
|
||||
valueType = GenericCollectionTypeResolver.getCollectionType(this.targetListClass);
|
||||
valueType = ResolvableType.forClass(this.targetListClass).asCollection().resolveGeneric();
|
||||
}
|
||||
if (valueType != null) {
|
||||
TypeConverter converter = getBeanTypeConverter();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -21,7 +21,7 @@ import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.ResolvableType;
|
||||
|
||||
/**
|
||||
* Simple factory for shared Map instances. Allows for central setup
|
||||
@@ -87,8 +87,9 @@ public class MapFactoryBean extends AbstractFactoryBean<Map<Object, Object>> {
|
||||
Class<?> keyType = null;
|
||||
Class<?> valueType = null;
|
||||
if (this.targetMapClass != null) {
|
||||
keyType = GenericCollectionTypeResolver.getMapKeyType(this.targetMapClass);
|
||||
valueType = GenericCollectionTypeResolver.getMapValueType(this.targetMapClass);
|
||||
ResolvableType mapType = ResolvableType.forClass(this.targetMapClass).asMap();
|
||||
keyType = mapType.resolveGeneric(0);
|
||||
valueType = mapType.resolveGeneric(1);
|
||||
}
|
||||
if (keyType != null || valueType != null) {
|
||||
TypeConverter converter = getBeanTypeConverter();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -21,7 +21,7 @@ import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.ResolvableType;
|
||||
|
||||
/**
|
||||
* Simple factory for shared Set instances. Allows for central setup
|
||||
@@ -86,7 +86,7 @@ public class SetFactoryBean extends AbstractFactoryBean<Set<Object>> {
|
||||
}
|
||||
Class<?> valueType = null;
|
||||
if (this.targetSetClass != null) {
|
||||
valueType = GenericCollectionTypeResolver.getCollectionType(this.targetSetClass);
|
||||
valueType = ResolvableType.forClass(this.targetSetClass).asCollection().resolveGeneric();
|
||||
}
|
||||
if (valueType != null) {
|
||||
TypeConverter converter = getBeanTypeConverter();
|
||||
|
||||
@@ -1148,6 +1148,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
Class<?> type = descriptor.getDependencyType();
|
||||
if (type.isArray()) {
|
||||
Class<?> componentType = type.getComponentType();
|
||||
ResolvableType resolvableType = descriptor.getResolvableType();
|
||||
Class<?> resolvedArrayType = resolvableType.resolve();
|
||||
if (resolvedArrayType != null && resolvedArrayType != type) {
|
||||
type = resolvedArrayType;
|
||||
componentType = resolvableType.getComponentType().resolve();
|
||||
}
|
||||
if (componentType == null) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
|
||||
new MultiElementDescriptor(descriptor));
|
||||
if (matchingBeans.isEmpty()) {
|
||||
@@ -1164,7 +1173,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
return result;
|
||||
}
|
||||
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
|
||||
Class<?> elementType = descriptor.getCollectionType();
|
||||
Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
|
||||
if (elementType == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -1184,11 +1193,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
return result;
|
||||
}
|
||||
else if (Map.class == type) {
|
||||
Class<?> keyType = descriptor.getMapKeyType();
|
||||
ResolvableType mapType = descriptor.getResolvableType().asMap();
|
||||
Class<?> keyType = mapType.resolveGeneric(0);
|
||||
if (String.class != keyType) {
|
||||
return null;
|
||||
}
|
||||
Class<?> valueType = descriptor.getMapValueType();
|
||||
Class<?> valueType = mapType.resolveGeneric(1);
|
||||
if (valueType == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user