提交 387c8a81 编写于 作者: J Juergen Hoeller

Differentiate between TypeDescriptors with same annotations but different attributes

Issue: SPR-13714
上级 06056e6a
...@@ -468,7 +468,7 @@ public class TypeDescriptor implements Serializable { ...@@ -468,7 +468,7 @@ public class TypeDescriptor implements Serializable {
return false; return false;
} }
for (Annotation ann : getAnnotations()) { for (Annotation ann : getAnnotations()) {
if (!other.hasAnnotation(ann.annotationType())) { if (!ann.equals(other.getAnnotation(ann.annotationType()))) {
return false; return false;
} }
} }
......
...@@ -478,6 +478,21 @@ public class GenericConversionServiceTests { ...@@ -478,6 +478,21 @@ public class GenericConversionServiceTests {
assertTrue(converter.getNestedMatchAttempts() > 0); assertTrue(converter.getNestedMatchAttempts() > 0);
} }
@Test
public void conditionalConverterCachingForDifferentAnnotationAttributes() throws Exception {
conversionService.addConverter(new ColorConverter());
conversionService.addConverter(new MyConditionalColorConverter());
assertEquals(Color.BLACK, conversionService.convert("000000xxxx",
new TypeDescriptor(getClass().getField("activeColor"))));
assertEquals(Color.BLACK, conversionService.convert(" #000000 ",
new TypeDescriptor(getClass().getField("inactiveColor"))));
assertEquals(Color.BLACK, conversionService.convert("000000yyyy",
new TypeDescriptor(getClass().getField("activeColor"))));
assertEquals(Color.BLACK, conversionService.convert(" #000000 ",
new TypeDescriptor(getClass().getField("inactiveColor"))));
}
@Test @Test
public void shouldNotSupportNullConvertibleTypesFromNonConditionalGenericConverter() { public void shouldNotSupportNullConvertibleTypesFromNonConditionalGenericConverter() {
GenericConverter converter = new NonConditionalGenericConverter(); GenericConverter converter = new NonConditionalGenericConverter();
...@@ -629,14 +644,49 @@ public class GenericConversionServiceTests { ...@@ -629,14 +644,49 @@ public class GenericConversionServiceTests {
} }
@ExampleAnnotation(active = true)
public String annotatedString;
@ExampleAnnotation(active = true)
public Color activeColor;
@ExampleAnnotation(active = false)
public Color inactiveColor;
public List<Integer> list;
public Map<String, Integer> map;
public Map<String, ?> wildcardMap;
@SuppressWarnings("rawtypes")
public Collection rawCollection;
public Collection<?> genericCollection;
public Collection<String> stringCollection;
public Collection<Integer> integerCollection;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
private static @interface ExampleAnnotation {} private @interface ExampleAnnotation {
boolean active();
}
private interface MyBaseInterface {
}
private static interface MyBaseInterface {}
private static interface MyInterface extends MyBaseInterface {} private interface MyInterface extends MyBaseInterface {
}
private static class MyInterfaceImplementer implements MyInterface {
}
private static class MyInterfaceImplementer implements MyInterface {}
private static class MyBaseInterfaceToStringConverter implements Converter<MyBaseInterface, String> { private static class MyBaseInterfaceToStringConverter implements Converter<MyBaseInterface, String> {
...@@ -646,6 +696,7 @@ public class GenericConversionServiceTests { ...@@ -646,6 +696,7 @@ public class GenericConversionServiceTests {
} }
} }
private static class MyStringArrayToResourceArrayConverter implements Converter<String[], Resource[]> { private static class MyStringArrayToResourceArrayConverter implements Converter<String[], Resource[]> {
@Override @Override
...@@ -654,6 +705,7 @@ public class GenericConversionServiceTests { ...@@ -654,6 +705,7 @@ public class GenericConversionServiceTests {
} }
} }
private static class MyStringArrayToIntegerArrayConverter implements Converter<String[], Integer[]> { private static class MyStringArrayToIntegerArrayConverter implements Converter<String[], Integer[]> {
@Override @Override
...@@ -662,6 +714,7 @@ public class GenericConversionServiceTests { ...@@ -662,6 +714,7 @@ public class GenericConversionServiceTests {
} }
} }
private static class MyStringToIntegerArrayConverter implements Converter<String, Integer[]> { private static class MyStringToIntegerArrayConverter implements Converter<String, Integer[]> {
@Override @Override
...@@ -671,6 +724,7 @@ public class GenericConversionServiceTests { ...@@ -671,6 +724,7 @@ public class GenericConversionServiceTests {
} }
} }
private static class WithCopyConstructor { private static class WithCopyConstructor {
WithCopyConstructor() {} WithCopyConstructor() {}
...@@ -679,6 +733,7 @@ public class GenericConversionServiceTests { ...@@ -679,6 +733,7 @@ public class GenericConversionServiceTests {
WithCopyConstructor(WithCopyConstructor value) {} WithCopyConstructor(WithCopyConstructor value) {}
} }
private static class MyConditionalConverter implements Converter<String, Color>, ConditionalConverter { private static class MyConditionalConverter implements Converter<String, Color>, ConditionalConverter {
private int matchAttempts = 0; private int matchAttempts = 0;
...@@ -699,6 +754,7 @@ public class GenericConversionServiceTests { ...@@ -699,6 +754,7 @@ public class GenericConversionServiceTests {
} }
} }
private static class NonConditionalGenericConverter implements GenericConverter { private static class NonConditionalGenericConverter implements GenericConverter {
@Override @Override
...@@ -712,6 +768,7 @@ public class GenericConversionServiceTests { ...@@ -712,6 +768,7 @@ public class GenericConversionServiceTests {
} }
} }
private static class MyConditionalGenericConverter implements GenericConverter, ConditionalConverter { private static class MyConditionalGenericConverter implements GenericConverter, ConditionalConverter {
private final List<TypeDescriptor> sourceTypes = new ArrayList<TypeDescriptor>(); private final List<TypeDescriptor> sourceTypes = new ArrayList<TypeDescriptor>();
...@@ -737,6 +794,7 @@ public class GenericConversionServiceTests { ...@@ -737,6 +794,7 @@ public class GenericConversionServiceTests {
} }
} }
private static class MyConditionalConverterFactory implements ConverterFactory<String, Color>, ConditionalConverter { private static class MyConditionalConverterFactory implements ConverterFactory<String, Color>, ConditionalConverter {
private MyConditionalConverter converter = new MyConditionalConverter(); private MyConditionalConverter converter = new MyConditionalConverter();
...@@ -768,11 +826,13 @@ public class GenericConversionServiceTests { ...@@ -768,11 +826,13 @@ public class GenericConversionServiceTests {
String getBaseCode(); String getBaseCode();
} }
private static interface MyEnumInterface extends MyEnumBaseInterface {
private interface MyEnumInterface extends MyEnumBaseInterface {
String getCode(); String getCode();
} }
private static enum MyEnum implements MyEnumInterface {
private enum MyEnum implements MyEnumInterface {
A("1"), A("1"),
B("2"), B("2"),
...@@ -795,7 +855,8 @@ public class GenericConversionServiceTests { ...@@ -795,7 +855,8 @@ public class GenericConversionServiceTests {
} }
} }
private static enum EnumWithSubclass {
private enum EnumWithSubclass {
FIRST { FIRST {
@Override @Override
...@@ -805,6 +866,7 @@ public class GenericConversionServiceTests { ...@@ -805,6 +866,7 @@ public class GenericConversionServiceTests {
} }
} }
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
private static class MyStringToRawCollectionConverter implements Converter<String, Collection> { private static class MyStringToRawCollectionConverter implements Converter<String, Collection> {
...@@ -814,6 +876,7 @@ public class GenericConversionServiceTests { ...@@ -814,6 +876,7 @@ public class GenericConversionServiceTests {
} }
} }
private static class MyStringToGenericCollectionConverter implements Converter<String, Collection<?>> { private static class MyStringToGenericCollectionConverter implements Converter<String, Collection<?>> {
@Override @Override
...@@ -822,6 +885,7 @@ public class GenericConversionServiceTests { ...@@ -822,6 +885,7 @@ public class GenericConversionServiceTests {
} }
} }
private static class MyEnumInterfaceToStringConverter<T extends MyEnumInterface> implements Converter<T, String> { private static class MyEnumInterfaceToStringConverter<T extends MyEnumInterface> implements Converter<T, String> {
@Override @Override
...@@ -830,14 +894,16 @@ public class GenericConversionServiceTests { ...@@ -830,14 +894,16 @@ public class GenericConversionServiceTests {
} }
} }
private static class StringToMyEnumInterfaceConverterFactory implements ConverterFactory<String, MyEnumInterface> { private static class StringToMyEnumInterfaceConverterFactory implements ConverterFactory<String, MyEnumInterface> {
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({"unchecked", "rawtypes"})
public <T extends MyEnumInterface> Converter<String, T> getConverter(Class<T> targetType) { public <T extends MyEnumInterface> Converter<String, T> getConverter(Class<T> targetType) {
return new StringToMyEnumInterfaceConverter(targetType); return new StringToMyEnumInterfaceConverter(targetType);
} }
private static class StringToMyEnumInterfaceConverter<T extends Enum<?> & MyEnumInterface> implements Converter<String, T> { private static class StringToMyEnumInterfaceConverter<T extends Enum<?> & MyEnumInterface> implements Converter<String, T> {
private final Class<T> enumType; private final Class<T> enumType;
public StringToMyEnumInterfaceConverter(Class<T> enumType) { public StringToMyEnumInterfaceConverter(Class<T> enumType) {
...@@ -855,9 +921,10 @@ public class GenericConversionServiceTests { ...@@ -855,9 +921,10 @@ public class GenericConversionServiceTests {
} }
} }
private static class StringToMyEnumBaseInterfaceConverterFactory implements ConverterFactory<String, MyEnumBaseInterface> { private static class StringToMyEnumBaseInterfaceConverterFactory implements ConverterFactory<String, MyEnumBaseInterface> {
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({"unchecked", "rawtypes"})
public <T extends MyEnumBaseInterface> Converter<String, T> getConverter(Class<T> targetType) { public <T extends MyEnumBaseInterface> Converter<String, T> getConverter(Class<T> targetType) {
return new StringToMyEnumBaseInterfaceConverter(targetType); return new StringToMyEnumBaseInterfaceConverter(targetType);
} }
...@@ -881,6 +948,7 @@ public class GenericConversionServiceTests { ...@@ -881,6 +948,7 @@ public class GenericConversionServiceTests {
} }
} }
private static class MyStringToStringCollectionConverter implements Converter<String, Collection<String>> { private static class MyStringToStringCollectionConverter implements Converter<String, Collection<String>> {
@Override @Override
...@@ -889,6 +957,7 @@ public class GenericConversionServiceTests { ...@@ -889,6 +957,7 @@ public class GenericConversionServiceTests {
} }
} }
private static class MyStringToIntegerCollectionConverter implements Converter<String, Collection<Integer>> { private static class MyStringToIntegerCollectionConverter implements Converter<String, Collection<Integer>> {
@Override @Override
...@@ -897,6 +966,7 @@ public class GenericConversionServiceTests { ...@@ -897,6 +966,7 @@ public class GenericConversionServiceTests {
} }
} }
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
private static class UntypedConverter implements Converter { private static class UntypedConverter implements Converter {
...@@ -906,28 +976,27 @@ public class GenericConversionServiceTests { ...@@ -906,28 +976,27 @@ public class GenericConversionServiceTests {
} }
} }
private static class ColorConverter implements Converter<String, Color> { private static class ColorConverter implements Converter<String, Color> {
@Override @Override
public Color convert(String source) { if (!source.startsWith("#")) source = "#" + source; return Color.decode(source); } public Color convert(String source) {
return Color.decode(source.trim());
}
} }
@ExampleAnnotation private static class MyConditionalColorConverter implements Converter<String, Color>, ConditionalConverter {
public String annotatedString;
public List<Integer> list;
public Map<String, Integer> map;
public Map<String, ?> wildcardMap;
@SuppressWarnings("rawtypes")
public Collection rawCollection;
public Collection<?> genericCollection;
public Collection<String> stringCollection;
public Collection<Integer> integerCollection; @Override
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
ExampleAnnotation ann = targetType.getAnnotation(ExampleAnnotation.class);
return (ann != null && ann.active());
}
@Override
public Color convert(String source) {
return Color.decode(source.substring(0, 6));
}
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册