跳到主要内容

生命周期事件

Doubao 中英对照 Lifecycle Events

Spring Data JDBC 向 ApplicationListener 对象发布生命周期事件,这些对象通常是应用程序上下文中的 bean。事件是关于某个生命周期阶段的通知。与实体回调不同,事件用于通知。事务性监听器会在事务完成时收到事件。事件和回调仅对聚合根触发。如果您想处理非根实体,则需要通过监听其所从属的聚合根来完成。

实体生命周期事件可能开销较大,您在加载大型结果集时可能会注意到性能特征的变化。您可以在模板 API上禁用生命周期事件。

例如,以下监听器会在聚合被保存之前被调用:

@Bean
ApplicationListener<BeforeSaveEvent<Object>> loggingSaves() {

return event -> {

Object entity = event.getEntity();
LOG.info("{} is getting saved.", entity);
};
}
java

如果您只想处理特定领域类型的事件,可以让您的监听器继承 AbstractRelationalEventListener,并覆盖一个或多个 onXXX 方法,其中 XXX 代表事件类型。回调方法仅会针对与该领域类型及其子类型相关的事件被调用,因此您无需进行进一步的类型转换。

class PersonLoadListener extends AbstractRelationalEventListener<Person> {

@Override
protected void onAfterLoad(AfterLoadEvent<Person> personLoad) {
LOG.info(personLoad.getEntity());
}
}
java

下表描述了可用的事件。有关处理步骤之间确切关系的更多详细信息,请参阅可用回调的描述,它与事件一一对应。

表 1. 可用事件

事件发布时机
BeforeDeleteEvent在聚合根被删除之前。
AfterDeleteEvent在聚合根被删除之后。
BeforeConvertEvent在聚合根被转换为用于执行 SQL 语句的计划之前,但在已经判断该聚合是否为新的之后,即已经判断应执行更新还是插入之后。
BeforeSaveEvent在聚合根被保存之前(即插入或更新之前,但在已经判断应插入还是更新之后)。
AfterSaveEvent在聚合根被保存之后(即插入或更新之后)。
AfterConvertEvent在从数据库 ResultSet 创建聚合根并设置好其所有属性之后。
注意

生命周期事件依赖于 ApplicationEventMulticaster,对于 SimpleApplicationEventMulticaster,可以为其配置 TaskExecutor,因此无法保证事件在何时被处理。

特定存储的 EntityCallbacks​

Spring Data JDBC 使用 EntityCallback API 来提供审计支持,并对下表中列出的回调作出响应。

表 2. Spring Data JDBC 所执行不同处理的处理步骤与回调

处理EntityCallback / 处理步骤说明
删除BeforeDeleteCallback在实际删除之前。
聚合根以及该聚合的所有实体都从数据库中移除。
AfterDeleteCallback在聚合被删除之后。
保存根据聚合是否为新的,判断应对该聚合执行插入还是更新。
BeforeConvertCallback如果您想以编程方式设置 id,这是正确的回调。在上一步中新聚合已被识别出来,而在这一步生成的 Id 会在下一步中使用。
将聚合转换为聚合变更,它是一系列要对数据库执行的 SQL 语句。在这一步中会判断 Id 是由聚合提供的,还是 Id 仍为空、预期由数据库生成。
BeforeSaveCallback对聚合根所做的更改可能会被考虑,但关于是否将 id 值发送到数据库的决定已在上一步中做出。不要用它为新聚合创建 Id,而应改用 BeforeConvertCallback。
上述确定的 SQL 语句对数据库执行。
AfterSaveCallback在聚合根被保存之后(即插入或更新之后)。
加载使用一条或多条 SQL 查询加载聚合。从结果集构造聚合。
AfterConvertCallback

我们鼓励使用回调而非事件,因为回调支持不可变类的使用,因此比事件更强大、更通用。

删除和保存相关的回调不会针对派生查询方法或注解查询被调用。一般而言,Spring Data JDBC 没有高效的方式来确定这些操作会影响哪些聚合,因此无法提供回调或事件。