Spring 类型转换器

发布于 2025-02-05 14:35:25 字数 5759 浏览 8 评论 0

1. GenericConverter

public interface GenericConverter {
  @Nullable
  Set<ConvertiblePair> getConvertibleTypes();

  @Nullable
  Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType);

  final class ConvertiblePair {
    private final Class<?> sourceType;
    private final Class<?> targetType;

    public ConvertiblePair(Class<?> sourceType, Class<?> targetType) {
      Assert.notNull(sourceType, "Source type must not be null");
      Assert.notNull(targetType, "Target type must not be null");
      this.sourceType = sourceType;
      this.targetType = targetType;
    }

    public Class<?> getSourceType() {
      return this.sourceType;
    }

    public Class<?> getTargetType() {
      return this.targetType;
    }

    @Override
    public boolean equals(@Nullable Object other) {
      if (this == other) {
        return true;
      }
      if (other == null || other.getClass() != ConvertiblePair.class) {
        return false;
      }
      ConvertiblePair otherPair = (ConvertiblePair) other;
      return (this.sourceType == otherPair.sourceType && this.targetType == otherPair.targetType);
    }

    @Override
    public int hashCode() {
      return (this.sourceType.hashCode() * 31 + this.targetType.hashCode());
    }

    @Override
    public String toString() {
      return (this.sourceType.getName() + " -> " + this.targetType.getName());
    }
  }

}

GenericConverter 中提供了两个方法:

  • Set getConvertibleTypes(); 用于获取转换的源类型和目标类型;
  • Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType); 用于转换类型

还定义了一个内部类,里面的结构很简单,指定源和目标的类型。

GenericConverter 比较常用的一个实现类是 ConditionalGenericConverter。

ConditionalGenericConverter 的作用只是将 GenericConverter 和 ConditionalConverter 接口的功能聚合。

ConditionalConverter 的作用是根据源和目标的类型判断该转换器是否支持。

public interface ConditionalConverter {
  boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}

以 ArrayToCollectionConverter 为类说明 ConditionalGenericConverter 的作用:

final class ArrayToCollectionConverter implements ConditionalGenericConverter {

  private final ConversionService conversionService;


  public ArrayToCollectionConverter(ConversionService conversionService) {
    this.conversionService = conversionService;
  }


  @Override
  public Set<ConvertiblePair> getConvertibleTypes() {
    return Collections.singleton(new ConvertiblePair(Object[].class, Collection.class));
  }

  @Override
  public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
    return ConversionUtils.canConvertElements(
        sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor(), this.conversionService);
  }

  @Override
  @Nullable
  public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
    if (source == null) {
      return null;
    }

    int length = Array.getLength(source);
    TypeDescriptor elementDesc = targetType.getElementTypeDescriptor();
    Collection<Object> target = CollectionFactory.createCollection(targetType.getType(),
        (elementDesc != null ? elementDesc.getType() : null), length);

    if (elementDesc == null) {
      for (int i = 0; i < length; i++) {
        Object sourceElement = Array.get(source, i);
        target.add(sourceElement);
      }
    }
    else {
      for (int i = 0; i < length; i++) {
        Object sourceElement = Array.get(source, i);
        Object targetElement = this.conversionService.convert(sourceElement,
            sourceType.elementTypeDescriptor(sourceElement), elementDesc);
        target.add(targetElement);
      }
    }
    return target;
  }

}

  • Set getConvertibleTypes();返回了源和目标类型。
  • match 方法实际上调用的是 GenericConversionService#canConvert
  @Override
  public boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
    Assert.notNull(targetType, "Target type to convert to cannot be null");
    if (sourceType == null) {
      return true;
    }
    GenericConverter converter = getConverter(sourceType, targetType);
    return (converter != null);
  }
@Nullable
  protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
    ConverterCacheKey key = new ConverterCacheKey(sourceType, targetType);
    GenericConverter converter = this.converterCache.get(key);
    if (converter != null) {
      return (converter != NO_MATCH ? converter : null);
    }

    converter = this.converters.find(sourceType, targetType);
    if (converter == null) {
      converter = getDefaultConverter(sourceType, targetType);
    }

    if (converter != null) {
      this.converterCache.put(key, converter);
      return converter;
    }

    this.converterCache.put(key, NO_MATCH);
    return null;
  }

这段代码中 converterCache 是 GenericConversionService 中定义的一个软引用类型。(在 jvm 满的时候(不够),会回收掉不可达对象和软引用对象)

private final Map<ConverterCacheKey, GenericConverter> converterCache = new ConcurrentReferenceHashMap<>(64);

ConversionService 是转换器的门面

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

情定在深秋

暂无简介

文章
评论
26 人气
更多

推荐作者

夢野间

文章 0 评论 0

百度③文鱼

文章 0 评论 0

小草泠泠

文章 0 评论 0

zhuwenyan

文章 0 评论 0

weirdo

文章 0 评论 0

坚持沉默

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文