Spring 中数据列表转换:ConversionService

Spring 框架的ConversionService在简化数据转换任务方面发挥着至关重要的作用,特别是将列表从一种类型转换为另一种类型。

将字符串列表转换为整数列表
数据类型的转换是一项常见任务,特别是在处理不同的数据输入和输出时。提供的代码片段是使用 Spring 转换功能将字符串列表转换为整数列表的绝佳示例。

在这里,我们利用Spring 的内置功能StringToNumberConverterFactory来实现此目的。这个概念可以扩展到其他列表类型集合,如 Set 或 LinkedList,展示了 Spring 在处理各种数据结构方面的转换能力的多功能性。

为了演示此功能,下面提供了ConversionServiceTest 。它展示了 Spring 的ConversionService在集合到集合类型转换中的实际使用,突出显示了关键组件及其在该过程中的角色。让我们深入研究一下细节:

@SpringBootTest
class ConversionServiceTest {

    @Autowired
    ConversionService conversionService;

    @Test
    void shouldConvert_ListStrings_to_Numbers() {
        List<String> stringList = List.of("1", "2", "3", "4");
        TypeDescriptor sourceType = TypeDescriptor.forObject(stringList);
        TypeDescriptor targetType = TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(Integer.class));
        List<Integer> convertedNumbers = (List<Integer>) conversionService.convert(stringList, sourceType, targetType);

        assertThat(convertedNumbers).isNotNull()
                .containsExactly(1, 2, 3, 4);
    }

    @Test
    void shouldConvert_SetOfStrings_to_Numbers() {
        List<String> stringList = List.of("1", "2", "3", "4");
        TypeDescriptor sourceType = TypeDescriptor.forObject(stringList);
        TypeDescriptor targetType = TypeDescriptor.collection(Set.class, TypeDescriptor.valueOf(Integer.class));
        // A LinkedHashSet
        Set<Integer> convertedNumbers = (Set<Integer>) conversionService.convert(stringList, sourceType, targetType);

        assertThat(convertedNumbers).isNotNull()
                .containsExactly(1, 2, 3, 4);
    }

}

在此代码中:
1.自动连线转换服务
ConversionService是 Spring Framework 中的一个接口,它定义了类型转换的契约。在这里,它是自动装配的,这意味着 Spring 将在运行时自动在基于 Web 的应用程序上提供实现。

在独立的 Spring 应用程序中,ConversionService bean 通常是使用应用程序的 Spring 配置中的ConversionServiceFactoryBean定义的。此设置初始化默认的 Spring 转换器,将它们无缝集成到应用程序上下文中。

@Configuration
public class ConversionServiceExampleConfig {

  @Bean
  ConversionServiceFactoryBean conversionService() {
      ConversionServiceFactoryBean factory = new ConversionServiceFactoryBean();
      factory.afterPropertiesSet();
      return factory;
  }

}


2. 测试方法——shouldConvert_Strings_to_Numbers()
此方法旨在测试字符串列表到整数列表的转换。

  • 字符串列表:首先定义一个字符串列表List.of(“1”, “2”, “3”, “4”),表示源数据。
  • 类型描述符:接下来,为源类型和目标类型创建TypeDescriptor对象。TypeDescriptor.forObject(stringList)描述源类型(字符串列表),TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(Integer.class))描述目标类型(整数列表)。
  • Conversion:实际的转换是由conversionService.convert(..)方法执行的,该方法以源对象 ( stringList ) 以及源和目标TypeDescriptor作为参数。此方法返回转换后的列表,转换为List<Integer>。
  • 断言:最后,测试断言(使用 AssertJ 断言)转换后的列表不为空,并且包含与原始字符串对应的精确整数 (1, 2, 3, 4)。

StringToNumberConverterFactory的作用
Spring 中的 StringToNumberConverterFactory是此转换过程中不可或缺的一部分。它为转换器提供了一个工厂,可以将字符串转换为各种数字类型,如整数、双精度、长整型等。在这种情况下,它自动处理列表中每个字符串到其相应整数值的转换。

来源:spring-core/../StringToNumberConverterFactory.java


final class StringToNumberConverterFactory implements ConverterFactory<String, Number> {

    @Override
    public <T extends Number> Converter<String, T> getConverter(Class<T> targetType) {
        return new StringToNumber<>(targetType);
    }


    private static final class StringToNumber<T extends Number> implements Converter<String, T> {

        private final Class<T> targetType;

        public StringToNumber(Class<T> targetType) {
            this.targetType = targetType;
        }

        @Override
        @Nullable
        public T convert(String source) {
            if (source.isEmpty()) {
                return null;
            }
            return NumberUtils.parseNumber(source, this.targetType);
        }
    }

}

要点
  • 此代码演示了一种使用 Spring 转换服务转换复杂数据结构的干净、类型安全的方法。
  • 它利用 Spring 的内置转换器工厂来处理常见的转换场景,从而减少了对自定义转换器实现的需求。
  • 使用TypeDescriptor可以精确控制源类型和目标类型,从而增强转换过程的稳健性。
  • 这种方法在经常需要这种动态类型转换的 Spring 应用程序中特别有用,例如在数据处理或处理来自各种源的输入时。

编写您自己的转换器
您可以通过实现 org.springframework.core.convert.converter.Converter 接口编写自己的转换器来进一步扩展该功能。
在此示例中,假设代码正在查询包含数据文件集合(txt、json、yaml 等)的 AWS S3 路径,这些数据文件将自动转换为MyBusinessObject。

public class S3ObjectSummaryConverterToMyBusinessObjectConverter implements Converter<S3ObjectSummary, MyBusinessObject> {

   public MyBusinessObject convert(S3ObjectSummary source) {
       // pull down data from AWS S3
       // convert to MyBusinessObject
      return myBusinessObject;
   }
    
}

综上所述
在本文中,我们探索了 Spring 转换服务的多功能且强大的功能,特别关注将字符串列表转换为整数以及针对 AWS S3ObjectSummary 对象等特定用例定制转换器。通过了解如何实现和利用 Spring 的内置转换器以及如何制作自己的转换器,您可以显着简化应用程序中的数据处理。提供的实际示例可作为将这些转换技术集成到实际场景中的基础,从而提高 Spring 应用程序的效率和健壮性。请记住,有效处理数据转换的能力是现代软件开发中的一项重要技能,而 Spring 的转换服务是实现这一目标的强大工具。