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
@FunctionalInterface
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 // ...
}
@Override
public int getOrder() {
return 100;
}
}
根据您的要求实现回调。
如果存在多个相同域类型的实体回调,则可能对实体回调进行排序。排序遵循最低优先级。
14.8.2.注册实体回调
EntityCallback如果 bean 在ApplicationContext. 大多数模板 API 已经实现ApplicationContextAware,因此可以访问ApplicationContext
以下示例解释了一组有效的实体回调注册:
示例 121. EntityCallbackBean 注册示例
@Order(1)
@Component
class First implements BeforeSaveCallback {
@Override
public Person onBeforeSave(Person person) {
return // ...
}
}
@Component
class DefaultingEntityCallback implements BeforeSaveCallback,
Ordered {
@Override
public Object onBeforeSave(Person entity, String collection) {
// ...
}
@Override
public int getOrder() {
return 100;
}
}
@Configuration
public class EntityCallbackConfiguration {
@Bean
BeforeSaveCallback<Person> unorderedLambdaReceiverCallback() {
return (BeforeSaveCallback<Person>) it -> // ...
}
}
@Component
class UserCallbacks implements BeforeConvertCallback,
BeforeSaveCallback<User> {
@Override
public Person onBeforeConvert(User user) {
return // ...
}
@Override
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 来提供审计支持并对以下回调做出反应。
Spring中国教育管理中心-Apache Cassandra 的 Spring 数据教程十四
- 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
org.jetbrains.kotlinx
kotlinx-coroutines-reactive
org.jetbrains.kotlinx
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接口时才被发现。