使用目标类型定义多个Spring转换器可选?

时间:2018-03-20 17:29:12

标签: java spring spring-mvc generics spring-boot

我正在使用Spring Boot 1.5.10并且我的自定义转换器出现问题。

我正在定义目标类型为Optional的多个转换器 像这样:

@Component
public class StringToSomeTypeConverter implements Converter<String, Optional<SomeType>> { ... }


@Component
public class StringToOtherTypeConverter implements Converter<String, Optional<OtherType>> { ... }

我的问题是,显然只有一个转换器注册了Optional类型。所以在运行时只在我的所有控制器中调用一个Converter。无论通用目标类型。 (示例中为SomeTypeOtherType

我做了一些挖掘,并在GenericConversionService#getConverter中选择了转换器。 该方法将TypeDescriptor targetType作为参数,并从ConverterCacheKeysourceType构建targetType。 遗憾的是,TypeDescriptor#equals仅比较getType()(可选)而非resolvableType(我们的示例中为SomeTypeOtherType)。 这解释了为什么只有一个转换器被拾取。

有没有办法让Spring知道ResolvableType所以我可以使用Optional作为多个转换器的目标类型?

1 个答案:

答案 0 :(得分:1)

我无法确定发生了什么,但是多次浏览过Spring MVC源代码我想这个问题会出现在一些代码中,这些代码是迭代注册转换器并检查它们是否可以转换,所以目标类型会如果您运行此代码,则是可选的(不是可选&lt; Class&lt; Integer&gt;&gt;,但是可选):

Optional<Class<String>> ops = Optional.of(String.class);
Optional<Class<Integer>> ops2 = Optional.of(Integer.class);
System.out.println(ops2.getClass().equals(ops.getClass()));

您将在控制台上看到它打印为true,这意味着它们被视为相同的数据类型!因此,如果Spring真正遍历转换器列表,那么总是会调用第一个,因为它可以处理所有可选对象,无论如何,我的建议是:

更新:如果你有兴趣在Spring框架上调试它,你必须在ConversionService接口的方法上放置一个断点,它是管理转换的服务,至少这是它在Spring Core中的工作方式,而你我们应该看到执行流程,并在一个时刻检查哪个转换器是合适的,如果其中一些转换器实现了ConditionalConverter,请自行查看此过程的核心方法之一:https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java#L560