关于spring:Spring认证中国教育管理中心Spring-Data-R2DBC框架教程四

37次阅读

共计 6442 个字符,预计需要花费 17 分钟才能阅读完成。

原题目:Spring 认证中国教育管理中心 -Spring Data R2DBC 框架教程四(Spring 中国教育管理中心)

14.3. 实体回调
Spring Data 基础设施提供了在调用某些办法之前和之后批改实体的钩子。那些所谓的 EntityCallback 实例提供了一种不便的办法来检查和潜在地以回调格调批改实体。
AnEntityCallback 看起来很像一个专门的 ApplicationListener. 一些 Spring Data 模块公布 BeforeSaveEvent 容许批改给定实体的存储特定事件(例如)。在某些状况下,例如应用不可变类型时,这些事件可能会导致麻烦。此外,事件公布依赖于
ApplicationEventMulticaster. 如果应用异步配置 TaskExecutor 它可能会导致不可预测的后果,因为事件处理能够分叉到线程上。

实体回调为同步 API 和反应式 API 提供集成点,以保障在解决链中定义明确的检查点按程序执行,返回潜在批改的实体或反应式包装器类型。

实体回调通常按 API 类型分隔。这种拆散意味着同步 API 仅思考同步实体回调,而反应式实现仅思考反应式实体回调。

Spring Data Commons 2.2 引入了实体回调 API。这是利用实体批改的举荐形式。在调用可能已注册的实例之前,ApplicationEvents 仍会公布特定于现有商店的信息。EntityCallback

14.3.1. 实现实体回调
AnEntityCallback 通过其泛型类型参数间接与其域类型相关联。每个 Spring Data 模块通常带有一组 EntityCallback 涵盖实体生命周期的预约义接口。

例 76. 解剖 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.
    */

T onBeforeSave(T entity <2>, String collection <3>);
}
BeforeSaveCallback 在保留实体之前要调用的特定办法。返回一个可能被批改的实例。

在长久化之前的实体。

许多存储特定参数,例如实体长久化到的汇合。

Spring 认证中国教育管理中心 -Spring Data R2DBC 框架教程四
例 77. 反应式的分析 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.
    */

Publisher<T> onBeforeSave(T entity <2>, String collection <3>);
}
BeforeSaveCallback 在保留实体之前,在订阅时调用的特定办法。收回一个可能被批改的实例。

在长久化之前的实体。

许多存储特定参数,例如实体长久化到的汇合。

Spring 认证中国教育管理中心 -Spring Data R2DBC 框架教程四
可选的实体回调参数由实现 Spring Data 模块定义并从 EntityCallback.callback().

实现适宜您的应用程序需要的接口,如下例所示:

示例 78. 示例 BeforeSaveCallback

class DefaultingEntityCallback implements BeforeSaveCallback<Person>, 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<Person> {

@Override
public Person onBeforeSave(Person person) {

return // ...

}
}

@Component
class DefaultingEntityCallback implements BeforeSaveCallback<Person>,

                                                       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<User>,

                                    BeforeSaveCallback<User> {

@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<T>SPI 接口,您必须实现该接口以告知基础设施以后与应用程序交互的用户或零碎是谁。泛型类型 T 定义了用什么类型正文的属性 @CreatedBy 或 @LastModifiedBy 必须是什么类型。

以下示例显示了应用 Spring SecurityAuthentication 对象的接口的实现:

Example 82.AuditorAware 基于 Spring Security 的实现

class SpringSecurityAuditorAware implements AuditorAware<User> {

@Override
public Optional<User> getCurrentAuditor() {

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<T>SPI 接口,您必须实现该接口能力通知基础设施以后与应用程序交互的用户或零碎是谁。泛型类型 T 定义了用什么类型正文的属性 @CreatedBy 或 @LastModifiedBy 必须是什么类型。

以下示例显示了应用响应式 Spring SecurityAuthentication 对象的接口的实现:

例 83.ReactiveAuditorAware 基于 Spring Security 的实现

class SpringSecurityAuditorAware implements ReactiveAuditorAware<User> {

@Override
public Mono<User> getCurrentAuditor() {

return ReactiveSecurityContextHolder.getContext()
            .map(SecurityContext::getAuthentication)
            .filter(Authentication::isAuthenticated)
            .map(Authentication::getPrincipal)
            .map(User.class::cast);

}
}
该实现拜访 AuthenticationSpring Security 提供的对象并查找 UserDetails 您在 UserDetailsService 实现中创立的自定义实例。咱们在这里假如您通过 UserDetails 实现公开域用户,但依据 Authentication 发现,您也能够从任何中央查找它。

正文完
 0