Spring Data 扩展

本节介绍了 Spring Data 的一组扩展,它们使得 Spring Data 可以在多种上下文中使用。目前,大多数集成都面向 Spring MVC。

Querydsl 扩展

Querydsl 是一个框架,它通过其流式 API 实现静态类型化的 SQL 式查询的构建。

Querydsl 的维护已放缓,社区已在 OpenFeign 下派生了该项目:github.com/OpenFeign/querydsl (groupId io.github.openfeign.querydsl)。Spring Data 在尽力而为的基础上支持此分支。

几个 Spring Data 模块通过 QuerydslPredicateExecutor 提供了与 Querydsl 的集成,如下例所示

QuerydslPredicateExecutor 接口
public interface QuerydslPredicateExecutor<T> {

  Optional<T> findById(Predicate predicate);  (1)

  Iterable<T> findAll(Predicate predicate);   (2)

  long count(Predicate predicate);            (3)

  boolean exists(Predicate predicate);        (4)

  // … more functionality omitted.
}
1 查找并返回与 Predicate 匹配的单个实体。
2 查找并返回与 Predicate 匹配的所有实体。
3 返回与 Predicate 匹配的实体数量。
4 返回是否存在与 Predicate 匹配的实体。

要使用 Querydsl 支持,请在您的 Repository 接口上扩展 QuerydslPredicateExecutor,如下例所示

Repository 中的 Querydsl 集成
interface UserRepository extends CrudRepository<User, Long>, QuerydslPredicateExecutor<User> {
}

上面的示例允许您通过使用 Querydsl Predicate 实例来编写类型安全的查询,如下例所示

Predicate predicate = user.firstname.equalsIgnoreCase("dave")
	.and(user.lastname.startsWithIgnoreCase("mathews"));

userRepository.findAll(predicate);

使用 Querydsl 的类型安全查询方法

MongoDB Repository 及其响应式对应部分与 Querydsl 项目集成,后者提供了一种执行类型安全查询的方式。

查询不是以内联字符串形式编写或外部化到 XML 文件中,而是通过流式 API 构建。
— Querydsl 团队

它提供以下功能

  • IDE 中的代码补全(所有属性、方法和操作都可以在您喜欢的 Java IDE 中展开)。

  • 几乎不允许语法无效的查询(在所有级别上都是类型安全的)。

  • 领域类型和属性可以安全地引用——不涉及字符串!

  • 更好地适应领域类型中的重构更改。

  • 增量式查询定义更容易。

有关如何使用 Maven 或 Ant 引导基于 APT 的代码生成环境的信息,请参阅Querydsl 文档

QueryDSL 允许您编写如下查询

  • 命令式

  • 响应式

QPerson person = QPerson.person;
List<Person> result = repository.findAll(person.address.zipCode.eq("C0123"));

Page<Person> page = repository.findAll(person.lastname.contains("a"),
                                       PageRequest.of(0, 2, Direction.ASC, "lastname"));
QPerson person = QPerson.person;

Flux<Person> result = repository.findAll(person.address.zipCode.eq("C0123"));

QPerson 是一个由 Java 注解处理器生成的类。有关如何使用构建系统设置注解处理的信息,请参阅设置注解处理。它是一个 Predicate,可让您编写类型安全的查询。请注意,除了 C0123 值之外,查询中没有字符串。

您可以通过使用 QuerydslPredicateExecutor / ReactiveQuerydslPredicateExecutor 接口来使用生成的 Predicate 类,如下所示

  • 命令式

  • 响应式

public interface QuerydslPredicateExecutor<T> {

    Optional<T> findOne(Predicate predicate);

    List<T> findAll(Predicate predicate);

    List<T> findAll(Predicate predicate, Sort sort);

    List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders);

    Page<T> findAll(Predicate predicate, Pageable pageable);

    List<T> findAll(OrderSpecifier<?>... orders);

    long count(Predicate predicate);

    boolean exists(Predicate predicate);

    <S extends T, R> R findBy(Predicate predicate, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);
}
interface ReactiveQuerydslPredicateExecutor<T> {

    Mono<T> findOne(Predicate predicate);

    Flux<T> findAll(Predicate predicate);

    Flux<T> findAll(Predicate predicate, Sort sort);

    Flux<T> findAll(Predicate predicate, OrderSpecifier<?>... orders);

    Flux<T> findAll(OrderSpecifier<?>... orders);

    Mono<Long> count(Predicate predicate);

    Mono<Boolean> exists(Predicate predicate);

    <S extends T, R, P extends Publisher<R>> P findBy(Predicate predicate,
            Function<FluentQuery.ReactiveFluentQuery<S>, P> queryFunction);
}

要在您的 Repository 实现中使用它,请将其添加到您的接口继承的 Repository 接口列表中,如下例所示

  • 命令式

  • 响应式

interface PersonRepository extends MongoRepository<Person, String>, QuerydslPredicateExecutor<Person> {

    // additional query methods go here
}
interface PersonRepository extends ReactiveMongoRepository<Person, String>, ReactiveQuerydslPredicateExecutor<Person> {

    // additional query methods go here
}
请注意,响应式 MongoDB 支持不支持 join(DBRef)。

设置注解处理

要在 Spring Data MongoDB 中使用 Querydsl,您需要在构建系统中设置注解处理,以生成 Q 类。虽然您可以手动编写 Q 类,但建议使用 Querydsl 注解处理器为您生成它们,以便您的 Q 类与您的领域模型保持同步。

Spring Data MongoDB 附带一个注解处理器 MongoAnnotationProcessor,默认情况下未注册。通常,注解处理器通过 Java 的服务加载器,通过 META-INF/services/javax.annotation.processing.Processor 进行注册,一旦它们在类路径上,也会被激活。大多数 Spring Data 用户不使用 Querydsl,因此对于无法从 Querydsl 中受益的项目来说,要求额外的强制依赖项是没有意义的。因此,您需要在构建系统中激活注解处理。

以下示例展示了如何在 Maven 和 Gradle 中通过提及依赖项和编译器配置更改来设置注解处理

  • Maven

  • Gradle

<dependencies>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-mongodb</artifactId>
    </dependency>

    <dependency>
        <groupId>com.querydsl</groupId>
        <artifactId>querydsl-mongodb</artifactId>
        <version>${querydslVersion}</version>

        <!-- Recommended: Exclude the mongo-java-driver to avoid version conflicts -->
        <exclusions>
            <exclusion>
                <groupId>org.mongodb</groupId>
                <artifactId>mongo-java-driver</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>com.querydsl</groupId>
        <artifactId>querydsl-apt</artifactId>
        <version>${querydslVersion}</version>
        <classifier>jakarta</classifier>
        <scope>provided</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <annotationProcessors>
                    <annotationProcessor>
                        org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor
                    </annotationProcessor>
                </annotationProcessors>

                <!-- Recommended: Some IDE's might require this configuration to include generated sources for IDE usage -->
                <generatedTestSourcesDirectory>target/generated-test-sources</generatedTestSourcesDirectory>
                <generatedSourcesDirectory>target/generated-sources</generatedSourcesDirectory>
            </configuration>
        </plugin>
    </plugins>
</build>
dependencies {
    implementation 'com.querydsl:querydsl-mongodb:${querydslVersion}'

    annotationProcessor 'com.querydsl:querydsl-apt:${querydslVersion}:jakarta'
    annotationProcessor 'org.springframework.data:spring-data-mongodb'

    testAnnotationProcessor 'com.querydsl:querydsl-apt:${querydslVersion}:jakarta'
    testAnnotationProcessor 'org.springframework.data:spring-data-mongodb'
}

tasks.withType(JavaCompile).configureEach {
    options.compilerArgs += [
            "-processor",
            "org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor"]
}

请注意,上述设置仅显示了最简单的用法,省略了您的项目可能需要的任何其他选项或依赖项。这种配置注解处理的方式会禁用 Java 的注解处理器扫描,因为 MongoDB 需要按类名指定 -processor。如果您正在使用其他注解处理器,您也需要将它们添加到 -processor/annotationProcessors 列表中。

Web 支持

支持 Repository 编程模型的 Spring Data 模块附带了各种 Web 支持。Web 相关组件需要在类路径上有 Spring MVC JAR。其中一些甚至提供了与 Spring HATEOAS 的集成。通常,通过在 JavaConfig 配置类中使用 @EnableSpringDataWebSupport 注解来启用集成支持,如下例所示

启用 Spring Data Web 支持
  • Java

  • XML

@Configuration
@EnableWebMvc
@EnableSpringDataWebSupport
class WebConfiguration {}
<bean class="org.springframework.data.web.config.SpringDataWebConfiguration" />

<!-- If you use Spring HATEOAS, register this one *instead* of the former -->
<bean class="org.springframework.data.web.config.HateoasAwareSpringDataWebConfiguration" />

@EnableSpringDataWebSupport 注解注册了一些组件。我们将在本节后面讨论这些组件。它还检测类路径上的 Spring HATEOAS,并为其注册集成组件(如果存在)。

基本 Web 支持

在 XML 中启用 Spring Data Web 支持

上一节中显示的配置注册了一些基本组件

  • 一个 使用 DomainClassConverter,用于让 Spring MVC 从请求参数或路径变量中解析 Repository 管理的领域类实例。

  • HandlerMethodArgumentResolver 实现,用于让 Spring MVC 从请求参数中解析 PageableSort 实例。

  • Jackson Modules 用于序列化/反序列化 PointDistance 等类型,或存储特定类型(取决于使用的 Spring Data 模块)。

使用 DomainClassConverter

DomainClassConverter 类允许您直接在 Spring MVC 控制器方法签名中使用领域类型,这样您就不需要通过 Repository 手动查找实例,如下例所示

在方法签名中使用领域类型的 Spring MVC 控制器
@Controller
@RequestMapping("/users")
class UserController {

  @RequestMapping("/{id}")
  String showUserForm(@PathVariable("id") User user, Model model) {

    model.addAttribute("user", user);
    return "userForm";
  }
}

该方法直接接收一个 User 实例,无需进一步查找。可以通过让 Spring MVC 首先将路径变量转换为领域类的 id 类型,最终通过对为该领域类型注册的 Repository 实例调用 findById(…) 来访问实例,从而解析该实例。

目前,Repository 必须实现 CrudRepository 才能有资格被发现用于转换。

Pageable 和 Sort 的 HandlerMethodArgumentResolvers

上一节中显示的配置代码片段还注册了一个 PageableHandlerMethodArgumentResolver 以及一个 SortHandlerMethodArgumentResolver 实例。该注册启用了 PageableSort 作为有效的控制器方法参数,如下例所示

将 Pageable 用作控制器方法参数
@Controller
@RequestMapping("/users")
class UserController {

  private final UserRepository repository;

  UserController(UserRepository repository) {
    this.repository = repository;
  }

  @RequestMapping
  String showUsers(Model model, Pageable pageable) {

    model.addAttribute("users", repository.findAll(pageable));
    return "users";
  }
}

上述方法签名会使 Spring MVC 尝试使用以下默认配置从请求参数中派生一个 Pageable 实例

表 1. 为 Pageable 实例评估的请求参数

page

您想要检索的页码。从 0 开始索引,默认为 0。

size

您想要检索的页大小。默认为 20。

sort

应排序的属性,格式为 property,property(,ASC|DESC)(,IgnoreCase)。默认排序方向是区分大小写的升序。如果您想切换方向或大小写敏感性,请使用多个 sort 参数,例如:?sort=firstname&sort=lastname,asc&sort=city,ignorecase

要自定义此行为,请分别注册一个实现 PageableHandlerMethodArgumentResolverCustomizer 接口或 SortHandlerMethodArgumentResolverCustomizer 接口的 bean。其 customize() 方法会被调用,允许您更改设置,如下例所示

@Bean SortHandlerMethodArgumentResolverCustomizer sortCustomizer() {
    return s -> s.setPropertyDelimiter("<-->");
}

如果设置现有 MethodArgumentResolver 的属性不足以满足您的目的,请扩展 SpringDataWebConfiguration 或其支持 HATEOAS 的对应类,覆盖 pageableResolver()sortResolver() 方法,并导入您的自定义配置文件,而不是使用 @Enable 注解。

如果您需要从请求中解析多个 PageableSort 实例(例如,对于多个表),您可以使用 Spring 的 @Qualifier 注解来区分它们。请求参数必须加上前缀 ${qualifier}_。以下示例显示了最终的方法签名

String showUsers(Model model,
      @Qualifier("thing1") Pageable first,
      @Qualifier("thing2") Pageable second) { … }

您必须填充 thing1_pagething2_page 等参数。

传递给方法的默认 Pageable 等同于 PageRequest.of(0, 20),但您可以通过在 Pageable 参数上使用 @PageableDefault 注解来自定义它。

Page 创建 JSON 表示

Spring MVC 控制器通常会尝试最终向客户端渲染 Spring Data 页面的表示。虽然可以直接从处理程序方法返回 Page 实例让 Jackson 按原样渲染,但我们强烈不建议这样做,因为底层实现类 PageImpl 是一个领域类型。这意味着我们可能出于无关原因而想或不得不更改其 API,而这些更改可能会以破坏性方式改变最终的 JSON 表示。

从 Spring Data 3.1 开始,我们通过发出描述该问题的警告日志来提示该问题。我们仍然最终建议利用 与 Spring HATEOAS 的集成,以一种完全稳定且启用超媒体的方式渲染页面,使客户端能够轻松导航。但从版本 3.3 开始,Spring Data 提供了一种方便使用但不需要包含 Spring HATEOAS 的页面渲染机制。

使用 Spring Data 的 PagedModel

该支持的核心是一个简化版的 Spring HATEOAS 的 PagedModel(Spring Data 中的版本位于 org.springframework.data.web 包中)。它可用于包装 Page 实例,并生成一个反映 Spring HATEOAS 建立的结构但省略导航链接的简化表示。

import org.springframework.data.web.PagedModel;

@Controller
class MyController {

  private final MyRepository repository;

  // Constructor ommitted

  @GetMapping("/page")
  PagedModel<?> page(Pageable pageable) {
    return new PagedModel<>(repository.findAll(pageable)); (1)
  }
}
1 Page 实例包装到 PagedModel 中。

这将产生一个看起来像这样的 JSON 结构

{
  "content" : [
     … // Page content rendered here
  ],
  "page" : {
    "size" : 20,
    "totalElements" : 30,
    "totalPages" : 2,
    "number" : 0
  }
}

请注意文档如何包含一个 page 字段,暴露了必要的 pagination 元数据。

全局启用简化的 Page 渲染

如果您不想更改所有现有的控制器来添加映射步骤以返回 PagedModel 而不是 Page,您可以通过如下方式调整 @EnableSpringDataWebSupport 来启用 PageImpl 实例到 PagedModel 的自动转换

@EnableSpringDataWebSupport(pageSerializationMode = VIA_DTO)
class MyConfiguration { }

这将允许您的控制器仍然返回 Page 实例,并且它们将自动被渲染为简化的表示

@Controller
class MyController {

  private final MyRepository repository;

  // Constructor ommitted

  @GetMapping("/page")
  Page<?> page(Pageable pageable) {
    return repository.findAll(pageable);
  }
}

PageSlice 的超媒体支持

Spring HATEOAS 附带了一个表示模型类(PagedModel/SlicedModel),它允许使用必要的 Page/Slice 元数据以及链接来丰富 PageSlice 实例的内容,使客户端能够轻松导航页面。将 Page 转换为 PagedModel 是通过 Spring HATEOAS RepresentationModelAssembler 接口的一个实现来完成的,该实现称为 PagedResourcesAssembler。类似地,Slice 实例可以使用 SlicedResourcesAssembler 转换为 SlicedModel。以下示例展示了如何将 PagedResourcesAssembler 用作控制器方法参数,SlicedResourcesAssembler 的工作方式完全相同

将 PagedResourcesAssembler 用作控制器方法参数
@Controller
class PersonController {

  private final PersonRepository repository;

  // Constructor omitted

  @GetMapping("/people")
  HttpEntity<PagedModel<Person>> people(Pageable pageable,
    PagedResourcesAssembler assembler) {

    Page<Person> people = repository.findAll(pageable);
    return ResponseEntity.ok(assembler.toModel(people));
  }
}

启用配置(如上例所示)允许将 PagedResourcesAssembler 用作控制器方法参数。对其调用 toModel(…) 会产生以下效果

  • Page 的内容成为 PagedModel 实例的内容。

  • PagedModel 对象附带一个 PageMetadata 实例,并填充了来自 Page 和底层 Pageable 的信息。

  • PagedModel 可能会附带 prevnext 链接,具体取决于页面的状态。这些链接指向方法映射到的 URI。添加到方法的分页参数与 PageableHandlerMethodArgumentResolver 的设置匹配,以确保稍后可以解析这些链接。

假设数据库中有 30 个 Person 实例。您现在可以触发一个请求(GET localhost:8080/people),并看到类似于以下内容的输出

{ "links" : [
    { "rel" : "next", "href" : "http://localhost:8080/persons?page=1&size=20" }
  ],
  "content" : [
     … // 20 Person instances rendered here
  ],
  "page" : {
    "size" : 20,
    "totalElements" : 30,
    "totalPages" : 2,
    "number" : 0
  }
}
此处显示的 JSON 包装格式不遵循任何正式指定的结构,也不保证稳定,我们随时可能更改它。强烈建议启用渲染,将其作为 Spring HATEOAS 支持的启用超媒体的官方媒体类型,例如 HAL。可以通过使用其 @EnableHypermediaSupport 注解来激活这些类型。更多信息请参见 Spring HATEOAS 参考文档

汇编器生成了正确的 URI,并也采纳了默认配置,用于在即将到来的请求中将参数解析为 Pageable。这意味着,如果更改该配置,链接也会自动遵循该更改。默认情况下,汇编器指向调用它的控制器方法,但您可以通过传递一个自定义的 Link 来作为构建分页链接的基础来定制这一点,这会重载 PagedResourcesAssembler.toModel(…) 方法。

Spring Data Jackson Modules

核心模块以及一些特定存储模块附带了一组 Jackson Modules,用于 Spring Data 领域使用的类型,如 org.springframework.data.geo.Distanceorg.springframework.data.geo.Point
一旦启用 web 支持 并且 com.fasterxml.jackson.databind.ObjectMapper 可用,就会导入这些 Modules。

在初始化期间,SpringDataJacksonModules,例如 SpringDataJacksonConfiguration,会被基础设施拾取,从而使得声明的 com.fasterxml.jackson.databind.Module 可供 Jackson ObjectMapper 使用。

以下领域类型的数据绑定 mixins 由通用基础设施注册。

org.springframework.data.geo.Distance
org.springframework.data.geo.Point
org.springframework.data.geo.Box
org.springframework.data.geo.Circle
org.springframework.data.geo.Polygon

各个模块可以提供额外的 SpringDataJacksonModules
更多详细信息请参阅特定存储部分。

Web 数据绑定支持

您可以使用 Spring Data projections(Projections 中描述)通过使用 JSONPath 表达式(需要 Jayway JsonPath)或 XPath 表达式(需要 XmlBeam)来绑定传入的请求负载,如下例所示

使用 JSONPath 或 XPath 表达式进行 HTTP 负载绑定
@ProjectedPayload
public interface UserPayload {

  @XBRead("//firstname")
  @JsonPath("$..firstname")
  String getFirstname();

  @XBRead("/lastname")
  @JsonPath({ "$.lastname", "$.user.lastname" })
  String getLastname();
}

您可以将上例中所示的类型用作 Spring MVC 处理程序方法的参数,或者通过在 RestTemplate 的某个方法上使用 ParameterizedTypeReference。前面的方法声明会尝试在给定文档的任何位置查找 firstnamelastname XML 查找是在传入文档的顶层执行的。其 JSON 变体首先尝试顶层的 lastname,如果前者没有返回值,也会尝试嵌套在 user 子文档中的 lastname。这样,可以轻松应对源文档结构的变化,而无需客户端调用公开的方法(这通常是基于类的负载绑定的缺点)。

支持嵌套 projections,如 Projections 中所述。如果方法返回复杂且非接口的类型,则使用 Jackson ObjectMapper 来映射最终值。

对于 Spring MVC,一旦 @EnableSpringDataWebSupport 激活并且所需的依赖项在类路径上可用,就会自动注册必要的转换器。对于与 RestTemplate 一起使用,请手动注册一个 ProjectingJackson2HttpMessageConverter (JSON) 或 XmlBeamHttpMessageConverter

更多信息请参见标准 Spring Data 示例 Repository 中的 Web projection 示例

Querydsl Web 支持

对于那些集成了 Querydsl 的存储,您可以从 Request 查询字符串中包含的属性派生查询。

考虑以下查询字符串

?firstname=Dave&lastname=Matthews

假设有前述示例中的 User 对象,您可以使用 QuerydslPredicateArgumentResolver 将查询字符串解析为以下值,如下所示

QUser.user.firstname.eq("Dave").and(QUser.user.lastname.eq("Matthews"))
当类路径上找到 Querydsl 时,该功能会与 @EnableSpringDataWebSupport 一起自动启用。

在方法签名中添加 @QuerydslPredicate 会提供一个即用型的 Predicate,您可以使用 QuerydslPredicateExecutor 来运行它。

类型信息通常从方法的返回类型中解析。由于该信息不一定与领域类型匹配,因此使用 QuerydslPredicateroot 属性可能是一个好主意。

以下示例展示了如何在方法签名中使用 @QuerydslPredicate

@Controller
class UserController {

  @Autowired UserRepository repository;

  @RequestMapping(value = "/", method = RequestMethod.GET)
  String index(Model model, @QuerydslPredicate(root = User.class) Predicate predicate,    (1)
          Pageable pageable, @RequestParam MultiValueMap<String, String> parameters) {

    model.addAttribute("users", repository.findAll(predicate, pageable));

    return "index";
  }
}
1 将查询字符串参数解析为与 User 匹配的 Predicate

默认绑定如下

  • 将简单属性上的 Object 绑定为 eq

  • 将集合类属性上的 Object 绑定为 contains

  • 将简单属性上的 Collection 绑定为 in

您可以通过 @QuerydslPredicatebindings 属性自定义这些绑定,或者通过使用 Java 8 的 default methods 并将 QuerydslBinderCustomizer 方法添加到 Repository 接口,如下所示

interface UserRepository extends CrudRepository<User, String>,
                                 QuerydslPredicateExecutor<User>,                (1)
                                 QuerydslBinderCustomizer<QUser> {               (2)

  @Override
  default void customize(QuerydslBindings bindings, QUser user) {

    bindings.bind(user.username).first((path, value) -> path.contains(value))    (3)
    bindings.bind(String.class)
      .first((StringPath path, String value) -> path.containsIgnoreCase(value)); (4)
    bindings.excluding(user.password);                                           (5)
  }
}
1 QuerydslPredicateExecutor 提供了访问特定查找方法以处理 Predicate
2 在 Repository 接口上定义的 QuerydslBinderCustomizer 会被自动拾取,并简化 @QuerydslPredicate(bindings=…​) 的使用。
3 username 属性的绑定定义为简单的 contains 绑定。
4 String 属性的默认绑定定义为不区分大小写的 contains 匹配。
5 Predicate 解析中排除 password 属性。
您可以注册一个持有默认 Querydsl 绑定的 QuerydslBinderCustomizerDefaults bean,然后在应用来自 Repository 或 @QuerydslPredicate 的特定绑定之前使用它们。

Repository Populators

如果您使用 Spring JDBC 模块,您可能熟悉使用 SQL 脚本填充 DataSource 的支持。在 Repository 级别也有类似的抽象,尽管它不使用 SQL 作为数据定义语言,因为它必须是存储无关的。因此,populators 支持 XML(通过 Spring 的 OXM 抽象)和 JSON(通过 Jackson)来定义用于填充 Repositories 的数据。

假设您有一个名为 data.json 的文件,内容如下

在 JSON 中定义的数据
[ { "_class" : "com.acme.Person",
 "firstname" : "Dave",
  "lastname" : "Matthews" },
  { "_class" : "com.acme.Person",
 "firstname" : "Carter",
  "lastname" : "Beauford" } ]

您可以使用 Spring Data Commons 中提供的 Repository 命名空间的 populator 元素来填充您的 Repositories。要将上述数据填充到您的 PersonRepository,请声明一个类似于以下的 populator

声明一个 Jackson repository populator
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:repository="http://www.springframework.org/schema/data/repository"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/repository
    https://www.springframework.org/schema/data/repository/spring-repository.xsd">

  <repository:jackson2-populator locations="classpath:data.json" />

</beans>

上述声明导致 data.json 文件被读取并由 Jackson ObjectMapper 反序列化。

JSON 对象解组到的类型通过检查 JSON 文档的 _class 属性来确定。基础设施最终会选择合适的 Repository 来处理已反序列化的对象。

要改为使用 XML 定义要填充到 Repositories 中的数据,您可以使用 unmarshaller-populator 元素。您可以配置它使用 Spring OXM 中可用的 XML marshaller 选项之一。详细信息请参见 Spring 参考文档。以下示例展示了如何使用 JAXB 解组 Repository populator

声明一个解组 Repository populator(使用 JAXB)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:repository="http://www.springframework.org/schema/data/repository"
  xmlns:oxm="http://www.springframework.org/schema/oxm"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/repository
    https://www.springframework.org/schema/data/repository/spring-repository.xsd
    http://www.springframework.org/schema/oxm
    https://www.springframework.org/schema/oxm/spring-oxm.xsd">

  <repository:unmarshaller-populator locations="classpath:data.json"
    unmarshaller-ref="unmarshaller" />

  <oxm:jaxb2-marshaller contextPath="com.acme" />

</beans>