Java 如何在Spring中使用CompletableFuture链接异步调用和传播异常

Java 如何在Spring中使用CompletableFuture链接异步调用和传播异常,java,spring,multithreading,asynchronous,completable-future,Java,Spring,Multithreading,Asynchronous,Completable Future,我对多线程和CompletableFuture非常陌生,我想知道是否可以在Spring容器(Spring Boot 2)和@Async中实现以下场景 我有几个基本上可以构建更大对象的服务,我想看看是否可以使粒度服务异步运行 我有一个服务(ServiceC),它依赖于另一个服务(ServiceA)的输出,而第三个服务可以独立运行(ServiceB)someService对于所有其他服务都是必需的,所以我认为不需要将其设置为异步调用。布局如下: @Service public class Servi

我对多线程和CompletableFuture非常陌生,我想知道是否可以在Spring容器(Spring Boot 2)和
@Async
中实现以下场景

我有几个基本上可以构建更大对象的服务,我想看看是否可以使粒度服务异步运行

我有一个服务(
ServiceC
),它依赖于另一个服务(
ServiceA
)的输出,而第三个服务可以独立运行(
ServiceB
someService
对于所有其他服务都是必需的,所以我认为不需要将其设置为异步调用。布局如下:

@Service
public class ServiceA {
  @Async
  public CompletableFuture<A> doServiceAWork(int id) throws AppException {
    return CompletableFuture.completedFuture(getA(id));
  }
}


@Service
public class ServiceB {
  @Async
  public CompletableFuture<B> doServiceBWork(int id) {
    return CompletableFuture.completedFuture(getB(id));
  }
}


@Service
public class ServiceC {
  @Async
  public CompletableFuture<C> doServiceCWork(A a) {
    return CompletableFuture.completedFuture(getC(a));
  }
}

@Service
public class ServiceOrchestration {
  // Necessary autorwiring of services

  public BigObj constructBigObj(AppObj obj) throw SomeAppException {
    int id = someService.getId(obj);
    BigObj bigObj = new BigObj();

    try {
      // Conceptualizing here
      CompletableFuture<A> cfA = serviceA.doServiceAWork(id);
      CompletableFuture<B> cfB = serviceB.doServiceBWork(id);

      // Obviously C depends on A
      CompletableFuture<C> cfC = serviceB.doServiceCWork(cfA.get());

      CompletableFuture.allOf(cfA, cfB, cfC).join();

      bigObj.setA(cfA.get());
      bigObj.setB(cfB.get());
      bigObj.setC(cfC.get());

    } catch (AppException | ExecutionException | InterruptedException e) {
      throw new SomeAppException("..", e);
    }

    return BigObj;
  }
}
@服务
公共类服务{
@异步的
公共CompletableFuture DoServiceWork(int id)引发AppException{
返回CompletableFuture.completedFuture(getA(id));
}
}
@服务
公共类服务B{
@异步的
公共CompletableFuture DosServiceBWork(内部id){
返回CompletableFuture.completedFuture(getB(id));
}
}
@服务
公共类服务{
@异步的
公共可完成的未来数据服务工作(A){
返回CompletableFuture.completedFuture(getC(a));
}
}
@服务
公共类服务编排{
//服务的必要布线
public BigObj constructionbigobj(AppObj obj)抛出一些appexception{
intid=someService.getId(obj);
BigObj BigObj=新的BigObj();
试一试{
//这里的概念化
CompletableFuture cfA=serviceA.DoServiceWork(id);
CompletableFuture cfB=serviceB.doServiceBWork(id);
//显然C依赖于A
CompletableFuture cfC=serviceB.doServiceWork(cfA.get());
CompletableFuture.allOf(cfA,cfB,cfC).join();
setA(cfA.get());
bigObj.setB(cfB.get());
setC(cfC.get());
}捕获(AppException | ExecutionException | InterruptedException e){
抛出新的异常(“…”,e);
}
返回BigObj;
}
}
我的要求如下:

  • ServiceA
    完成时,调用对
    ServiceC
    的异步调用,因为返回的数据应馈送到
    ServiceC
    以继续

  • 如果对
    ServiceA
    的调用引发异常(
    AppException
    ),则需要将其传播到调用方——在本例中为
    serviceordchestration\constructionbigObject()
    ,调用方如上所述进行处理。换句话说,如果
    serviceA.doServiceAWork(id)
    抛出异常,则应取消其他所有异步调用,但应在
    constructBigObj
    中抛出异常,以便捕获和处理

  • 等待所有异步调用完成,然后构造
    BigObj

对于第二个需求,我查看了
isCompletedExceptionally()
,但不确定需要从何处调用它,例如在调用
join()
之前?那么如何获取根异常呢

异步链接是如何在
ServiceA
调用和
ServiceC
之间工作的,其中调用一个有依赖关系,同时,我需要这两个值,例如
A
C
,来构造
BigObj