實體回呼
Spring Data 基礎架構提供 hook,用於在調用某些方法之前和之後修改實體。 這些所謂的 EntityCallback
實例提供了一種以回呼方式檢查和潛在修改實體的便捷方法。EntityCallback
看起來很像一個專門的 ApplicationListener
。 某些 Spring Data 模組發布特定於儲存體的事件(例如 BeforeSaveEvent
),這些事件允許修改給定的實體。 在某些情況下,例如使用不可變類型時,這些事件可能會導致問題。 此外,事件發布依賴於 ApplicationEventMulticaster
。 如果使用非同步 TaskExecutor
配置它,則可能會導致不可預測的結果,因為事件處理可能會 fork 到一個 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 | 許多特定於儲存體的參數,例如實體持久化到的*集合*。 |
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 特定方法,在訂閱時調用,在實體保存之前。 發出一個潛在修改的實例。 |
2 | 即將持久化的實體。 |
3 | 許多特定於儲存體的參數,例如實體持久化到的*集合*。 |
可選的實體回呼參數由實作 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 | 根據您的需求實作回呼。 |
2 | 如果同一域類型存在多個實體回呼,則可以對實體回呼進行排序。 排序遵循最低優先順序。 |
註冊實體回呼
EntityCallback
beans 由特定於儲存體的實作拾取,如果它們在 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` 介面實作接收其順序。 |
3 | BeforeSaveCallback 使用 lambda 表達式。 預設為無序且最後調用。 請注意,由 lambda 表達式實作的回呼不公開類型資訊,因此使用不可分配的實體調用這些回呼會影響回呼吞吐量。 使用 `class` 或 `enum` 來啟用回呼 bean 的類型篩選。 |
4 | 在單個實作類中組合多個實體回呼介面。 |