跳到主要内容
版本:5.4.3

实体回调

DeepSeek V3 中英对照 Entity Callbacks

Spring Data 基础设施提供了在某些方法调用前后修改实体的钩子。这些所谓的 EntityCallback 实例提供了一种便捷的方式,以回调风格检查和潜在修改实体。
EntityCallback 看起来非常像专门化的 ApplicationListener。一些 Spring Data 模块会发布特定于存储的事件(例如 BeforeSaveEvent),这些事件允许修改给定的实体。在某些情况下,例如处理不可变类型时,这些事件可能会引发问题。此外,事件发布依赖于 ApplicationEventMulticaster。如果使用异步的 TaskExecutor 进行配置,可能会导致不可预测的结果,因为事件处理可能会被分叉到一个线程中。

实体回调(Entity callbacks)提供了与同步和响应式 API 的集成点,以确保在处理链中的明确定义的检查点处按顺序执行,返回可能被修改的实体或响应式包装类型。

实体回调通常按 API 类型进行分离。这种分离意味着同步 API 只考虑同步实体回调,而响应式实现只考虑响应式实体回调。

备注

Entity Callback API 是在 Spring Data Commons 2.2 中引入的。它是应用实体修改的推荐方式。现有的特定存储的 ApplicationEvents 仍然会在调用可能注册的 EntityCallback 实例之前发布。

实现实体回调​

EntityCallback 通过其泛型类型参数直接与其域类型关联。每个 Spring Data 模块通常附带一组预定义的 EntityCallback 接口,涵盖实体的生命周期。

@FunctionalInterface
public interface BeforeSaveCallback<T> extends EntityCallback<T> {

/**
* Entity callback method invoked before a domain object is saved.
* Can return either the same or a modified instance.
*
* @return the domain object to be persisted.
*/
1
T onBeforeSave(T entity, 2
String collection); 3
}
  • BeforeSaveCallback 是在实体保存之前调用的特定方法。返回一个可能被修改的实例。

  • 实体在持久化之前的状态。

  • 一些存储特定的参数,例如实体持久化到的 collection。

@FunctionalInterface
public interface ReactiveBeforeSaveCallback<T> extends EntityCallback<T> {

/**
* Entity callback method invoked on subscription, before a domain object is saved.
* The returned Publisher can emit either the same or a modified instance.
*
* @return Publisher emitting the domain object to be persisted.
*/
1
Publisher<T> onBeforeSave(T entity, 2
String collection); 3
}
  • BeforeSaveCallback 是在实体保存之前,在订阅上调用的特定方法。它发出一个可能被修改的实例。

  • 实体在持久化之前的状态。

  • 一些存储特定的参数,例如实体持久化到的 collection。

备注

可选的实体回调参数由实现 Spring Data 模块定义,并从 EntityCallback.callback() 的调用站点推断。

根据您的应用程序需求实现接口,如下例所示:

class DefaultingEntityCallback implements BeforeSaveCallback<Person>, Ordered {      2

@Override
public Object onBeforeSave(Person entity, String collection) { 1

if(collection == "user") {
return // ...
}

return // ...
}

@Override
public int getOrder() {
return 100; 2
}
}
  • 根据你的要求实现回调。

  • 如果存在多个相同域类型的实体回调,可能会对实体回调进行排序。排序遵循最低优先级。

注册实体回调​

EntityCallback bean 会被存储特定的实现类所接收,前提是它们已在 ApplicationContext 中注册。大多数模板 API 已经实现了 ApplicationContextAware,因此可以访问 ApplicationContext。

以下示例解释了一组有效的实体回调注册:

@Order(1)                                                           1
@Component
class First implements BeforeSaveCallback<Person> {

@Override
public Person onBeforeSave(Person person) {
return // ...
}
}

@Component
class DefaultingEntityCallback implements BeforeSaveCallback<Person>,
Ordered { 2

@Override
public Object onBeforeSave(Person entity, String collection) {
// ...
}

@Override
public int getOrder() {
return 100; 2
}
}

@Configuration
public class EntityCallbackConfiguration {

@Bean
BeforeSaveCallback<Person> unorderedLambdaReceiverCallback() { 3
return (BeforeSaveCallback<Person>) it -> // ...
}
}

@Component
class UserCallbacks implements BeforeConvertCallback<User>,
BeforeSaveCallback<User> { 4

@Override
public Person onBeforeConvert(User user) {
return // ...
}

@Override
public Person onBeforeSave(User user) {
return // ...
}
}
  • BeforeSaveCallback 通过 @Order 注解接收其顺序。

  • BeforeSaveCallback 通过实现 Ordered 接口接收其顺序。

  • BeforeSaveCallback 使用 lambda 表达式。默认情况下无序并在最后调用。请注意,由 lambda 表达式实现的回调不会暴露类型信息,因此在调用这些回调时使用不可分配的实体会影响回调的吞吐量。使用 class 或 enum 来启用回调 bean 的类型过滤。

  • 在单个实现类中组合多个实体回调接口。

特定于存储的 EntityCallbacks​

Spring Data Elasticsearch 在内部使用 EntityCallback API 来支持审计功能,并对以下回调作出反应:

表 1. 支持的实体回调

回调方法描述顺序
Reactive/BeforeConvertCallbackonBeforeConvert(T entity, IndexCoordinates index)在领域对象转换为 org.springframework.data.elasticsearch.core.document.Document 之前调用。可以返回 entity 或一个修改后的实体,然后将其转换为文档。Ordered.LOWEST_PRECEDENCE
Reactive/AfterLoadCallbackonAfterLoad(Document document, Class<T> type, IndexCoordinates indexCoordinates)在从 Elasticsearch 读取结果并转换为 org.springframework.data.elasticsearch.core.document.Document 后调用。Ordered.LOWEST_PRECEDENCE
Reactive/AfterConvertCallbackonAfterConvert(T entity, Document document, IndexCoordinates indexCoordinates)在从 Elasticsearch 读取结果数据并将 org.springframework.data.elasticsearch.core.document.Document 转换为领域对象后调用。Ordered.LOWEST_PRECEDENCE
Reactive/AuditingEntityCallbackonBeforeConvert(Object entity, IndexCoordinates index)标记一个可审计实体的 创建 或 修改100
Reactive/AfterSaveCallbackT onAfterSave(T entity, IndexCoordinates index)在领域对象保存后调用。Ordered.LOWEST_PRECEDENCE