14.8.1.實作實體回調
AnEntityCallback通過其泛型類型參數直接與其域類型相關聯。每個 Spring Data 子產品通常帶有一組EntityCallback涵蓋實體生命周期的預定義接口。
例 118. 解剖 EntityCallback
@FunctionalInterface
public interface BeforeSaveCallback extends EntityCallback {
/**
- 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.
*/
T onBeforeSave(T entity <2>, String collection <3>);
}
BeforeSaveCallback在儲存實體之前要調用的特定方法。傳回一個可能被修改的執行個體。
在持久化之前的實體。
許多存儲特定參數,例如實體持久化到的集合。
例 119. 反應式的剖析 EntityCallback
public interface ReactiveBeforeSaveCallback extends EntityCallback {
- 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.
Publisher onBeforeSave(T entity <2>, String collection <3>);
BeforeSaveCallback在儲存實體之前,在訂閱時調用的特定方法。發出一個可能被修改的執行個體。
可選的實體回調參數由實作 Spring Data 子產品定義并從EntityCallback.callback().
實作适合您的應用程式需求的接口,如下例所示:
示例 120. 示例 BeforeSaveCallback
class DefaultingEntityCallback implements BeforeSaveCallback, Ordered {
@Override
public Object onBeforeSave(Person entity, String collection) {
if(collection == "user") {
return // ...
}
return // ...
public int getOrder() {
return 100;
根據您的要求實作回調。
如果存在多個相同域類型的實體回調,則可能對實體回調進行排序。排序遵循最低優先級。
14.8.2.注冊實體回調
EntityCallback如果 bean 在ApplicationContext. 大多數模闆 API 已經實作ApplicationContextAware,是以可以通路ApplicationContext
以下示例解釋了一組有效的實體回調注冊:
示例 121. EntityCallbackBean 注冊示例
@Order(1)
@Component
class First implements BeforeSaveCallback {
public Person onBeforeSave(Person person) {
return // ...
class DefaultingEntityCallback implements BeforeSaveCallback,
Ordered {
// ...
return 100;
@Configuration
public class EntityCallbackConfiguration {
@Bean
BeforeSaveCallback<Person> unorderedLambdaReceiverCallback() {
return (BeforeSaveCallback<Person>) it -> // ...
}
class UserCallbacks implements BeforeConvertCallback,
BeforeSaveCallback<User> {
public Person onBeforeConvert(User user) {
return // ...
public Person onBeforeSave(User user) {
return // ...
Spring中國教育管理中心-Apache Cassandra 的 Spring 資料教程十四
BeforeSaveCallback從@Order注釋中接收其指令。
BeforeSaveCallback通過Ordered接口實作接收其訂單。
BeforeSaveCallback使用 lambda 表達式。預設情況下無序并最後調用。請注意,由 lambda 表達式實作的回調不會公開類型資訊,是以使用不可配置設定的實體調用這些會影響回調吞吐量。使用classorenum為回調 bean 啟用類型過濾。
在單個實作類中組合多個實體回調接口。
14.8.3.存儲特定的 EntityCallbacks
Spring Data for Apache Cassandra 使用EntityCallbackAPI 來提供審計支援并對以下回調做出反應。
- Kotlin 支援
Kotlin是一種面向 JVM(和其他平台)的靜态類型語言,它允許編寫簡潔優雅的代碼,同時提供與用 Java 編寫的現有庫的出色互操作性。
Spring Data 為 Kotlin 提供一流的支援,讓開發人員幾乎可以像編寫 Kotlin 原生架構一樣編寫 Kotlin 應用程式。
使用 Kotlin 建構 Spring 應用程式的最簡單方法是利用 Spring Boot 及其專用的 Kotlin 支援。本綜合教程将教您如何使用start.spring.io使用 Kotlin 建構 Spring Boot 應用程式。
15.1.要求
Spring Data 支援 Kotlin 1.3 并要求kotlin-stdlib(或其變體之一,例如kotlin-stdlib-jdk8)和kotlin-reflect存在于類路徑中。如果您通過start.spring.io引導 Kotlin 項目,則預設提供這些。
15.2.零安全
Kotlin 的關鍵特性之一是空安全,它null在編譯時幹淨地處理值。這通過可空性聲明和“值或無值”語義的表達使應用程式更安全,而無需支付包裝器的成本,例如Optional. (Kotlin 允許使用具有可為空值的函數式構造。請參閱Kotlin 空值安全性綜合指南。)
盡管 Java 不允許您在其類型系統中表達空安全性,但 Spring Data API 使用包中聲明的JSR-305工具友好注釋進行了注釋org.springframework.lang。預設情況下,來自 Kotlin 中使用的 Java API 的類型被識别為平台類型,對其進行空檢查。 Kotlin 對 JSR-305 注釋和 Spring 可空性注釋的支援為Kotlin 開發人員提供了整個 Spring Data API 的空安全,具有null在編譯時處理相關問題的優勢。
請參閱存儲庫方法的空處理如何将空安全應用于 Spring 資料存儲庫。
您可以通過添加-Xjsr305帶有以下選項的編譯器标志來配置 JSR-305 檢查:-Xjsr305={strict|warn|ignore}.
對于 Kotlin 1.1+ 版本,預設行為與-Xjsr305=warn. strict考慮到 Spring Data API 空安全,該值是必需的。Kotlin 類型是從 Spring API 推斷出來的,但在使用時應該知道 Spring API 可空性聲明可以演變,即使在次要版本之間也是如此,并且将來可能會添加更多檢查。
尚不支援通用類型參數、可變參數和數組元素可空性,但應在即将釋出的版本中提供。
15.3.對象映射
有關Kotlin對象如何具體化的詳細資訊,請參閱Kotlin 支援。
15.4.擴充
Kotlin擴充提供了使用附加功能擴充現有類的能力。Spring Data Kotlin API 使用這些擴充為現有的 Spring API 添加新的 Kotlin 特定的便利。
請記住,需要導入 Kotlin 擴充才能使用。與靜态導入類似,IDE 應該在大多數情況下自動建議導入。
例如,Kotlin reified 類型參數為 JVM泛型類型擦除提供了一種解決方法,Spring Data 提供了一些擴充來利用此功能。這允許更好的 Kotlin API。
要SWCharacter在 Java 中檢索對象清單,您通常會編寫以下内容:
Flux characters = template.query(SWCharacter.class).inTable("star-wars").all()
使用 Kotlin 和 Spring Data 擴充,您可以改為編寫以下内容:
val characters = template.query().inTable("star-wars").all()
// or (both are equivalent)
val characters : Flux = template.query().inTable("star-wars").all()
在 Java 中,charactersKotlin 是強類型的,但 Kotlin 巧妙的類型推斷允許使用更短的文法。
Spring Data for Apache Cassandra 提供以下擴充:
為具體化泛型的支援CassandraOperations(包括異步和反應性的變體), CqlOperations(包括異步和反應性變體)FluentCassandraOperations,ReactiveFluentCassandraOperations,Criteria,和Query。
的協程擴充ReactiveFluentCassandraOperations。
15.5.協程
Kotlin協程是輕量級線程,允許強制編寫非阻塞代碼。在語言方面,suspend函數為異步操作提供了抽象,而在庫方面kotlinx.coroutines提供了async { }像Flow.
Spring Data 子產品在以下範圍内提供對協程的支援:
Kotlin 擴充中的延遲和流傳回值支援
15.5.1.依賴關系
協同程式支援時啟用kotlinx-coroutines-core,
kotlinx-coroutines-reactive而且kotlinx-coroutines-reactor依賴在類路徑中:
示例 122. 在 Maven pom.xml 中添加的依賴項
org.jetbrains.kotlinx
kotlinx-coroutines-core
kotlinx-coroutines-reactive
kotlinx-coroutines-reactor
支援的版本1.3.0及以上。
15.5.2.反應如何轉化為協程?
對于傳回值,從 Reactive 到 Coroutines API 的轉換如下:
fun handler(): Mono 變成 suspend fun handler()
fun handler(): Mono成為suspend fun handler(): T或suspend fun handler(): T?取決于是否Mono可以為空(具有更靜态類型的優點)
fun handler(): Flux 變成 fun handler(): Flow
FlowFlux在 Coroutines 世界中是等價的,适用于熱流或冷流,有限流或無限流,主要差別如下:
Flow是基于推的,Flux而是推拉混合的
背壓是通過挂起函數實作的
Flow隻有一個挂起collect方法,操作符作為擴充實作
由于協程,運算符易于實作
擴充允許添加自定義運算符 Flow
收集操作正在暫停功能
map運算符支援異步操作(不需要flatMap),因為它需要一個挂起函數參數
閱讀這篇關于Going Reactive with Spring、Coroutines 和 Kotlin Flow 的部落格文章,了解更多詳細資訊,包括如何與 Coroutines 并發運作代碼。
15.5.3.存儲庫
這是一個 Coroutines 存儲庫的示例:
interface CoroutineRepository : CoroutineCrudRepository<User, String> {
suspend fun findOne(id: String): User
fun findByFirstname(firstname: String): Flow<User>
suspend fun findAllByFirstname(id: String): List<User>
協程存儲庫建立在反應式存儲庫上,以通過 Kotlin 的協程公開資料通路的非阻塞特性。協程存儲庫上的方法可以由查詢方法或自定義實作支援。如果自定義方法是可調用的,則調用自定義實作方法會将 Coroutines 調用傳播到實際實作方法,suspend而無需實作方法傳回反應類型,例如Mono或Flux。
協程存儲庫僅在存儲庫擴充CoroutineCrudRepository接口時才被發現。