ric*_*din 6 java spring spring-cache completable-future spring-async
我需要缓存一些异步计算的结果.详细地说,为了克服这个问题,我试图使用Spring 4.3缓存和异步计算功能.
举个例子,我们来看下面的代码:
@Service
class AsyncService {
@Async
@Cacheable("users")
CompletableFuture<User> findById(String usedId) {
// Some code that retrieves the user relative to id userId
return CompletableFuture.completedFuture(user);
}
}
Run Code Online (Sandbox Code Playgroud)
可能吗?我的意思是,Spring的缓存抽象是否会正确处理类型的对象CompletableFuture<User>?我知道Caffeine Cache有类似的东西,但是我无法理解如果Spring正确配置它是否会使用它.
编辑:我对User对象本身不感兴趣,但是CompletableFuture代表了计算.
社区要我做一些实验,所以我做了.我发现我的问题的答案很简单:如果将它们置于同一方法之上@Cacheable,@Async则不能一起工作.
为了清楚起见,我没有想办法让缓存直接返回a所拥有的对象CompletableFuture.这是不可能的,如果不是这样,这将打破合同异步计算的的CompletableFuture类.
正如我所说,这两个注释不能在同一个方法上一起工作.如果你考虑一下,很明显.使用@Async一种方法进行标记,该方法也@Cacheable意味着将整个缓存管理委派给不同的异步线程.如果计算值的值CompletableFuture需要很长时间才能完成,那么缓存中的值将在Spring Proxy之后放置.
显然,有一个解决方法.解决方法使用的事实CompletableFuture是承诺.我们来看看下面的代码.
@Component
public class CachedService {
/* Dependecies resolution code */
private final AsyncService service;
@Cacheable(cacheNames = "ints")
public CompletableFuture<Integer> randomIntUsingSpringAsync() throws InterruptedException {
final CompletableFuture<Integer> promise = new CompletableFuture<>();
// Letting an asynchronous method to complete the promise in the future
service.performTask(promise);
// Returning the promise immediately
return promise;
}
}
@Component
public class AsyncService {
@Async
void performTask(CompletableFuture<Integer> promise) throws InterruptedException {
Thread.sleep(2000);
// Completing the promise asynchronously
promise.complete(random.nextInt(1000));
}
}
Run Code Online (Sandbox Code Playgroud)
诀窍是创建一个不完整的promise并立即从@Cacheable标注注释的方法返回它.承诺将由另一个bean异步完成,该bean拥有@Async标注注释的方法.
作为奖励,我还实现了一个不使用Spring @Async注释的解决方案,但它直接使用了CompletableFuture类中可用的工厂方法.
@Cacheable(cacheNames = "ints1")
public CompletableFuture<Integer> randomIntNativelyAsync() throws
InterruptedException {
return CompletableFuture.supplyAsync(this::getAsyncInteger, executor);
}
private Integer getAsyncInteger() {
logger.info("Entering performTask");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return random.nextInt(1000);
}
Run Code Online (Sandbox Code Playgroud)
无论如何,我在我的GitHub上分享了问题的完整解决方案,spring-cacheable-async.
最后,以上是对Jira SPR-12967所指的内容的详细描述.
希望能帮助到你.干杯.
| 归档时间: |
|
| 查看次数: |
3442 次 |
| 最近记录: |