此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Data MongoDB 4.4.0! |
生命周期事件
MongoDB 映射框架包括多个org.springframework.context.ApplicationEvent
应用程序可以通过在ApplicationContext
.
基于 Spring 的ApplicationContext
事件基础结构使其他产品(例如 Spring Integration)能够轻松接收这些事件,因为它们是基于 Spring 的应用程序中众所周知的事件机制。
实体生命周期事件的成本可能很高,并且在加载大型结果集时,您可能会注意到性能配置文件发生了变化。 您可以在 Template API 上禁用生命周期事件。
要在对象通过转换过程之前拦截对象(这会将您的域对象转换为org.bson.Document
),则可以注册AbstractMongoEventListener
,这会覆盖onBeforeConvert
方法。
当调度事件时,您的侦听器将被调用并在 domain 对象进入转换器之前传递它。
以下示例显示了如何执行此作:
public class BeforeConvertListener extends AbstractMongoEventListener<Person> {
@Override
public void onBeforeConvert(BeforeConvertEvent<Person> event) {
... does some auditing manipulation, set timestamps, whatever ...
}
}
要在对象进入数据库之前拦截它,你可以注册一个AbstractMongoEventListener
,这会覆盖onBeforeSave
方法。当调度事件时,您的侦听器将被调用并传递域对象和转换后的com.mongodb.Document
.以下示例显示了如何执行此作:
public class BeforeSaveListener extends AbstractMongoEventListener<Person> {
@Override
public void onBeforeSave(BeforeSaveEvent<Person> event) {
… change values, delete them, whatever …
}
}
在 Spring ApplicationContext 中声明这些 bean 会导致在调度事件时调用它们。
回调开启AbstractMappingEventListener
:
-
onBeforeConvert
:已调用MongoTemplate
insert
,insertList
和save
作,然后再将对象转换为Document
由MongoConverter
. -
onBeforeSave
:已调用MongoTemplate
insert
,insertList
和save
作,然后再插入或保存Document
在数据库中。 -
onAfterSave
:已调用MongoTemplate
insert
,insertList
和save
插入或保存Document
在数据库中。 -
onAfterLoad
:已调用MongoTemplate
find
,findAndRemove
,findOne
和getCollection
方法。Document
已从数据库中检索。 -
onAfterConvert
:已调用MongoTemplate
find
,findAndRemove
,findOne
和getCollection
方法。Document
已从数据库中检索到 POJO 中。
生命周期事件仅针对根级别类型发出。
在文档根中用作属性的复杂类型不受事件发布的约束,除非它们是用@DBRef . |
生命周期事件依赖于ApplicationEventMulticaster ,如果SimpleApplicationEventMulticaster 可以配置TaskExecutor ,因此不保证何时处理 Event。 |
实体回调
Spring Data 基础结构提供了用于在调用某些方法之前和之后修改实体的钩子。
那些所谓的EntityCallback
实例提供了一种方便的方法来检查和可能修改回调样式中的实体。
一EntityCallback
看起来非常像一个专门的ApplicationListener
.
某些 Spring Data 模块发布特定于存储的事件(例如BeforeSaveEvent
),允许修改给定实体。在某些情况下,例如在使用不可变类型时,这些事件可能会导致麻烦。
此外,事件发布依赖于ApplicationEventMulticaster
.如果使用异步TaskExecutor
这可能会导致不可预测的结果,因为事件处理可能会分叉到 Thread 上。
实体回调为集成点提供同步和反应式 API,以保证在处理链中定义明确的检查点按顺序执行,返回可能修改的实体或反应式包装器类型。
实体回调通常按 API 类型分隔。这种分离意味着同步 API 仅考虑同步实体回调,而反应式实现仅考虑反应式实体回调。
实体回调 API 已在 Spring Data Commons 2.2 中引入。这是应用实体修改的推荐方法。
现有商店特定 |
实现实体回调
一EntityCallback
通过其泛型类型参数直接与其域类型关联。
每个 Spring Data 模块通常附带一组预定义的EntityCallback
涵盖实体生命周期的接口。
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)
}
1 | BeforeSaveCallback 在保存实体之前调用的特定方法。返回可能修改的实例。 |
2 | 实体。 |
3 | 许多特定于 store 的参数,例如实体持久化到的集合。 |
EntityCallback
@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)
}
1 | BeforeSaveCallback 在保存实体之前在 Subscription 上调用的特定方法。发出可能修改的实例。 |
2 | 实体。 |
3 | 许多特定于 store 的参数,例如实体持久化到的集合。 |
可选的实体回调参数由实现的 Spring Data 模块定义,并从EntityCallback.callback() . |
实现适合您应用程序需求的接口,如以下示例所示:
BeforeSaveCallback
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)
}
}
1 | 根据您的需求实现 callback。 |
2 | 如果存在同一域类型的多个实体回调,则可能会对实体回调进行排序。排序遵循最低优先级。 |
注册实体回调
EntityCallback
bean 由 store 特定的实现拾取,以防它们在ApplicationContext
.
大多数模板 API 已经实现了ApplicationContextAware
因此可以访问ApplicationContext
以下示例说明了有效实体回调注册的集合:
EntityCallback
Bean 注册@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 // ...
}
}
1 | BeforeSaveCallback 从@Order 注解。 |
2 | BeforeSaveCallback 通过Ordered interface 实现。 |
3 | BeforeSaveCallback 使用 Lambda 表达式。默认情况下未排序,最后调用。请注意,由 lambda 表达式实现的回调不会公开键入信息,因此使用不可分配的实体调用这些回调会影响回调吞吐量。使用class 或enum 为回调 Bean 启用类型过滤。 |
4 | 将多个实体回调接口合并到一个实现类中。 |
存储特定的 EntityCallbacks
Spring Data MongoDB 使用EntityCallback
API 的审计支持,并对以下回调做出反应。
回调 | 方法 | 描述 | 次序 |
---|---|---|---|
|
|
在将域对象转换为 |
|
|
|
在加载域对象后调用。 |
|
|
|
标记已创建或修改的可审计实体 |
100 |
|
|
在保存域对象之前调用。 |
|
|
|
在保存域对象之前调用。 |
|