_原题是:Spring认证中国教育管理中心-Spring Data R2DBC框架教程四(Spring中国教育管理中心)
14.3.实体回调
Spring Data 基础设施提供了在调用某些方法之前和之后修改实体的钩子。那些所谓的EntityCallback实例提供了一种方便的方法来检查和潜在地以回调风格修改实体。
AnEntityCallback看起来很像一个专门的ApplicationListener. 一些 Spring Data 模块发布BeforeSaveEvent允许修改给定实体的存储特定事件(例如)。在某些情况下,例如使用不可变类型时,这些事件可能会导致麻烦。此外,事件发布依赖于
ApplicationEventMulticaster. 如果使用异步配置TaskExecutor它可能会导致不可预测的结果,因为事件处理可以分叉到线程上。
实体回调为同步 API 和反应式 API 提供集成点,以保证在处理链中定义明确的检查点按顺序执行,返回潜在修改的实体或反应式包装器类型。
【Spring认证中国教育管理中心-Spring Data R2DBC框架教程四】实体回调通常按 API 类型分隔。这种分离意味着同步 API 仅考虑同步实体回调,而反应式实现仅考虑反应式实体回调。
Spring Data Commons 2.2 引入了实体回调 API。这是应用实体修改的推荐方式。在调用可能已注册的实例之前,ApplicationEvents仍会发布特定于现有商店的信息。EntityCallback
14.3.1.实现实体回调
AnEntityCallback通过其泛型类型参数直接与其域类型相关联。每个 Spring Data 模块通常带有一组EntityCallback涵盖实体生命周期的预定义接口。
例 76. 解剖 EntityCallback
@FunctionalInterface
public interface BeforeSaveCallback
/**
T onBeforeSave(T entity <2>, String collection <3>);
*
*/
}
BeforeSaveCallback在保存实体之前要调用的特定方法。返回一个可能被修改的实例。
在持久化之前的实体。
许多存储特定参数,例如实体持久化到的集合。
Spring认证中国教育管理中心-Spring Data R2DBC框架教程四
例 77. 反应式的剖析 EntityCallback
@FunctionalInterface
public interface ReactiveBeforeSaveCallback
/**
Publisher
*
*/
}
BeforeSaveCallback在保存实体之前,在订阅时调用的特定方法。发出一个可能被修改的实例。
在持久化之前的实体。
许多存储特定参数,例如实体持久化到的集合。
Spring认证中国教育管理中心-Spring Data R2DBC框架教程四
可选的实体回调参数由实现 Spring Data 模块定义并从EntityCallback.callback().
实现适合您的应用程序需求的接口,如下例所示:
示例 78. 示例 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;
}
}
根据您的要求实现回调。
如果存在多个相同域类型的实体回调,则可能对实体回调进行排序。排序遵循最低优先级。
Spring认证中国教育管理中心-Spring Data R2DBC框架教程四
14.3.2.注册实体回调
EntityCallback如果 bean 在ApplicationContext. 大多数模板 API 已经实现ApplicationContextAware,因此可以访问ApplicationContext
以下示例解释了一组有效的实体回调注册:
示例 79. 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 unorderedLambdaReceiverCallback() {
return (BeforeSaveCallback) it -> // ...
}
}
@Component
class UserCallbacks implements BeforeConvertCallback
BeforeSaveCallback
@Override
public Person onBeforeConvert(User user) {
return // ...
}
@Override
public Person onBeforeSave(User user) {
return // ...
}
}
BeforeSaveCallback从@Order注释中接收其命令。
BeforeSaveCallback通过Ordered接口实现接收其订单。
BeforeSaveCallback使用 lambda 表达式。默认情况下无序并最后调用。请注意,由 lambda 表达式实现的回调不会公开类型信息,因此使用不可分配的实体调用这些会影响回调吞吐量。使用classorenum为回调 bean 启用类型过滤。
在单个实现类中组合多个实体回调接口。
Spring认证中国教育管理中心-Spring Data R2DBC框架教程四
Spring认证中国教育管理中心-Spring Data R2DBC框架教程四
14.3.3.存储特定的 EntityCallbacks
Spring Data R2DBC 使用EntityCallbackAPI 作为其审计支持并对以下回调做出反应。
Spring认证中国教育管理中心-Spring Data R2DBC框架教程四
14.4.使用多个数据库
当使用多个可能不同的数据库时,您的应用程序将需要不同的配置方法。所提供的
AbstractR2dbcConfiguration支持类假定单个ConnectionFactory从中Dialect得到的。话虽如此,您需要自己定义一些 bean 来配置 Spring Data R2DBC 以处理多个数据库。
R2DBC 存储库需要R2dbcEntityOperations实现存储库。无需使用即可扫描存储库的简单配置
AbstractR2dbcConfiguration如下所示:
@Configuration
@EnableR2dbcRepositories(basePackages = "com.acme.mysql", entityOperationsRef = "mysqlR2dbcEntityOperations")
static class MySQLConfiguration {
@Bean
@Qualifier("mysql")
public ConnectionFactory mysqlConnectionFactory() {
return …
}@Bean
public R2dbcEntityOperations mysqlR2dbcEntityOperations(@Qualifier("mysql") ConnectionFactory connectionFactory) {DatabaseClient databaseClient = DatabaseClient.create(connectionFactory);
return new R2dbcEntityTemplate(databaseClient, MySqlDialect.INSTANCE);
}
}
请注意,@EnableR2dbcRepositories允许通过databaseClientRef或进行配置entityOperationsRef。DatabaseClient连接到多个相同类型的数据库时,使用各种bean 很有用。当使用方言不同的不同数据库系统时,请改用@EnableR2dbcRepositories(entityOperationsRef = ...)`。
15.1.基本
Spring Data 提供了复杂的支持,以透明地跟踪谁创建或更改了实体以及更改发生的时间。要从该功能中受益,您必须为实体类配备审计元数据,这些元数据可以使用注释或通过实现接口来定义。此外,必须通过 Annotation 配置或 XML 配置启用审计以注册所需的基础架构组件。有关配置示例,请参阅特定于商店的部分。
仅跟踪创建和修改日期的应用程序不需要指定AuditorAware.
15.1.1.基于注解的审计元数据
我们提供@CreatedBy并@LastModifiedBy捕获创建或修改实体的用户,@CreatedDate并@LastModifiedDate捕获更改发生的时间。
示例 80. 一个被审计的实体
class Customer {
@CreatedBy
private User user;
@CreatedDate
private Instant createdDate;
// … further properties omitted
}
如您所见,可以有选择地应用注释,具体取决于您要捕获的信息。进行更改时捕获的注释可用于 Joda-Time DateTime、旧版 JavaDate和Calendar、JDK8 日期和时间类型以及long或类型的属性Long。
审计元数据不一定需要存在于根级实体中,但可以添加到嵌入式实体中(取决于实际使用的存储),如下面的截图所示。
示例 81. 审计嵌入实体中的元数据
class Customer {
private AuditMetadata auditingMetadata;
// … further properties omitted
}
class AuditMetadata {
@CreatedBy
private User user;
@CreatedDate
private Instant createdDate;
}
15.1.2.基于接口的审计元数据
如果您不想使用注释来定义审计元数据,您可以让您的域类实现该Auditable接口。它公开了所有审计属性的 setter 方法。
15.1.3.AuditorAware
如果您使用@CreatedBy或@LastModifiedBy,审计基础结构需要以某种方式了解当前主体。为此,我们提供了一个AuditorAware
以下示例显示了使用 Spring SecurityAuthentication对象的接口的实现:
Example 82.AuditorAware基于 Spring Security 的实现
class SpringSecurityAuditorAware implements AuditorAware
@Override
public Optional
return Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.filter(Authentication::isAuthenticated)
.map(Authentication::getPrincipal)
.map(User.class::cast);
}
}
该实现访问AuthenticationSpring Security 提供的对象并查找UserDetails您在UserDetailsService实现中创建的自定义实例。我们在这里假设您通过UserDetails实现公开域用户,但根据Authentication发现,您也可以从任何地方查找它。
15.1.4.ReactiveAuditorAware
使用反应式基础架构时,您可能希望使用上下文信息来提供@CreatedBy或提供@LastModifiedBy信息。我们提供了一个ReactiveAuditorAware
以下示例显示了使用响应式 Spring SecurityAuthentication对象的接口的实现:
例 83.ReactiveAuditorAware基于 Spring Security 的实现
class SpringSecurityAuditorAware implements ReactiveAuditorAware
@Override
public Mono
return ReactiveSecurityContextHolder.getContext()
.map(SecurityContext::getAuthentication)
.filter(Authentication::isAuthenticated)
.map(Authentication::getPrincipal)
.map(User.class::cast);
}
}
该实现访问AuthenticationSpring Security 提供的对象并查找UserDetails您在UserDetailsService实现中创建的自定义实例。我们在这里假设您通过UserDetails实现公开域用户,但根据Authentication发现,您也可以从任何地方查找它。
推荐阅读
- =======j2ee|spring用注解实现注入的@resource,@autowired,@inject区别
- jar|springboot项目打成jar包和war包,并部署(快速打包部署)
- 数据库|效率最高的Excel数据导入---(c#调用SSIS Package将数据库数据导入到Excel文件中【附源代码下载】)...
- java人生|35K 入职华为Java开发那天,我哭了(这 5 个月做的一切都值了)
- Java毕业设计项目实战篇|Java项目:在线嘿嘿网盘系统设计和实现(java+Springboot+ssm+mysql+maven)
- 微服务|微服务系列:服务发现与注册-----Eureka(面试突击!你想了解的Eureka都在这里.持续更新中......)
- java|ApplicationListener和SpringApplicationRunListener的联系
- Spring|SpringSecurity--自定义登录页面、注销登录配置
- 性能|性能工具之 Jmeter 通过 SpringBoot 工程启动
- 代码狂魔|Spring源码分析之IOC容器初始化流程