ConversionService detects generic type declaration on target class behind proxy as well
Issue: SPR-14822
(cherry picked from commit f7d740f)
This commit is contained in:
@@ -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.
|
||||
@@ -34,7 +34,7 @@ public interface ConverterFactory<S, R> {
|
||||
* Get the converter to convert from S to target type T, where T is also an instance of R.
|
||||
* @param <T> the target type
|
||||
* @param targetType the target type to convert to
|
||||
* @return A converter from S to T
|
||||
* @return a converter from S to T
|
||||
*/
|
||||
<T extends R> Converter<S, T> getConverter(Class<T> targetType);
|
||||
|
||||
|
||||
@@ -49,12 +49,12 @@ public interface ConverterRegistry {
|
||||
/**
|
||||
* Add a ranged converter factory to this registry.
|
||||
* The convertible source/target type pair is derived from the ConverterFactory's parameterized types.
|
||||
* @throws IllegalArgumentException if the parameterized types could not be resolved.
|
||||
* @throws IllegalArgumentException if the parameterized types could not be resolved
|
||||
*/
|
||||
void addConverterFactory(ConverterFactory<?, ?> converterFactory);
|
||||
void addConverterFactory(ConverterFactory<?, ?> factory);
|
||||
|
||||
/**
|
||||
* Remove any converters from sourceType to targetType.
|
||||
* Remove any converters from {@code sourceType} to {@code targetType}.
|
||||
* @param sourceType the source type
|
||||
* @param targetType the target type
|
||||
*/
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.DecoratingProxy;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.ConversionFailedException;
|
||||
@@ -96,9 +97,14 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
|
||||
@Override
|
||||
public void addConverter(Converter<?, ?> converter) {
|
||||
ResolvableType[] typeInfo = getRequiredTypeInfo(converter, Converter.class);
|
||||
Assert.notNull(typeInfo, "Unable to the determine sourceType <S> and targetType " +
|
||||
"<T> which your Converter<S, T> converts between; declare these generic types.");
|
||||
ResolvableType[] typeInfo = getRequiredTypeInfo(converter.getClass(), Converter.class);
|
||||
if (typeInfo == null && converter instanceof DecoratingProxy) {
|
||||
typeInfo = getRequiredTypeInfo(((DecoratingProxy) converter).getDecoratedClass(), Converter.class);
|
||||
}
|
||||
if (typeInfo == null) {
|
||||
throw new IllegalArgumentException("Unable to determine source type <S> and target type <T> for your " +
|
||||
"Converter [" + converter.getClass().getName() + "]; does the class parameterize those types?");
|
||||
}
|
||||
addConverter(new ConverterAdapter(converter, typeInfo[0], typeInfo[1]));
|
||||
}
|
||||
|
||||
@@ -115,11 +121,16 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConverterFactory(ConverterFactory<?, ?> converterFactory) {
|
||||
ResolvableType[] typeInfo = getRequiredTypeInfo(converterFactory, ConverterFactory.class);
|
||||
Assert.notNull(typeInfo, "Unable to the determine source type <S> and target range type R which your " +
|
||||
"ConverterFactory<S, R> converts between; declare these generic types.");
|
||||
addConverter(new ConverterFactoryAdapter(converterFactory,
|
||||
public void addConverterFactory(ConverterFactory<?, ?> factory) {
|
||||
ResolvableType[] typeInfo = getRequiredTypeInfo(factory.getClass(), ConverterFactory.class);
|
||||
if (typeInfo == null && factory instanceof DecoratingProxy) {
|
||||
typeInfo = getRequiredTypeInfo(((DecoratingProxy) factory).getDecoratedClass(), ConverterFactory.class);
|
||||
}
|
||||
if (typeInfo == null) {
|
||||
throw new IllegalArgumentException("Unable to determine source type <S> and target type <T> for your " +
|
||||
"ConverterFactory [" + factory.getClass().getName() + "]; does the class parameterize those types?");
|
||||
}
|
||||
addConverter(new ConverterFactoryAdapter(factory,
|
||||
new ConvertiblePair(typeInfo[0].resolve(), typeInfo[1].resolve())));
|
||||
}
|
||||
|
||||
@@ -284,8 +295,8 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
|
||||
// Internal helpers
|
||||
|
||||
private ResolvableType[] getRequiredTypeInfo(Object converter, Class<?> genericIfc) {
|
||||
ResolvableType resolvableType = ResolvableType.forClass(converter.getClass()).as(genericIfc);
|
||||
private ResolvableType[] getRequiredTypeInfo(Class<?> converterClass, Class<?> genericIfc) {
|
||||
ResolvableType resolvableType = ResolvableType.forClass(converterClass).as(genericIfc);
|
||||
ResolvableType[] generics = resolvableType.getGenerics();
|
||||
if (generics.length < 2) {
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user