【发布时间】:2021-07-21 04:28:14
【问题描述】:
如何防止在某些条件下运行 AfterSaveCallback (say AfterSaveCallback<Foo>)。我们希望避免触发AfterSaveCallback,即使它存在并已注册。如何做到这一点?
【问题讨论】:
标签: spring-boot spring-data-elasticsearch
如何防止在某些条件下运行 AfterSaveCallback (say AfterSaveCallback<Foo>)。我们希望避免触发AfterSaveCallback,即使它存在并已注册。如何做到这一点?
【问题讨论】:
标签: spring-boot spring-data-elasticsearch
AFAIK,Spring Data 不提供开箱即用的此类功能,但您可以通过自己实现它来实现所需的行为。
AfterSaveCallback 回调由AbstractElasticsearchTemplate 中定义的方法maybeCallbackAfterSave 调用:
protected <T> T maybeCallbackAfterSave(T entity, IndexCoordinates index) {
if (entityCallbacks != null) {
return entityCallbacks.callback(AfterSaveCallback.class, entity, index);
}
return entity;
}
我们的想法是通过扩展ElasticsearchRestTemplate 来为此方法提供自定义实现。例如:
public class CustomElasticsearchRestTemplate extends ElasticsearchRestTemplate {
public CustomElasticsearchRestTemplate(RestHighLevelClient client) {
super(client);
}
public CustomElasticsearchRestTemplate(RestHighLevelClient client, ElasticsearchConverter elasticsearchConverter) {
super(client, elasticsearchConverter);
}
@Override
protected <T> T maybeCallbackAfterSave(T entity, IndexCoordinates index) {
// compute as necessary
boolean shouldSkipCallback = ...;
// if the conditions are met for the callback not to be applied,
// just return the entity
if (shouldSkipCallback) {
return entity;
}
// else, proceed with the default implementation
return super.maybeCallbackAfterSave(entity);
}
}
根据用例,覆盖maybeCallbackAfterSave 的匿名类也适用。
然后,单独使用此自定义ElasticsearchRestTemplate 或以您认为合适的方式将其注册为应用程序默认值,例如,通过扩展AbstractElasticsearchConfiguration - 请参阅this great article - 或直接提供您自己的配置 -见this for an example。
该解决方案有一个缺点,即处理通用的T entity 参数。为此,它可能会有所帮助,我们可以将DefaultEntityCallbacks 中为callback processing 定义的代码作为参考,尤其是以下几行:
Class<T> entityType = (Class<T>) (entity != null ? ClassUtils.getUserClass(entity.getClass())
: callbackDiscoverer.resolveDeclaredEntityType(callbackType).getRawClass());
如您所见,他们使用ClassUtils 中的functionality implemented 来检测实际的类类型。
也许你可以利用这些知识,做一些类似于以下代码的事情来确定是否应该应用回调:
// Determine the class using one Spring magic
Class<T> entityType = (Class<T>)
ClassUtils.getUserClass(entity.getClass());
// Then, compare with the appropriate types that should be excluded
boolean shouldSkipCallback = entityType.isAssignableFrom(Foo.class);
作为替代方案,您可以向您的AfterSaveCallback<T> 实现提供参数化类型T 的类信息:这将允许您根据onAfterSave 上的具体类确定是否应该应用回调方法调用。
【讨论】: