0

我开始CompletableFuture在 Spring Boot 中使用,我在某些地方看到通常的存储库方法返回CompletableFuture <Entity>而不是Entity.

我不知道发生了什么,但是当我返回CompletableFuture存储库中的实例时,代码运行完美。但是,当我返回实体时,代码不会异步工作并且总是返回null.

这是一个例子:

@Service
public class AsyncServiceImpl{
    /** .. Init repository instances .. **/

    @Async(AsyncConfiguration.TASK_EXECUTOR_SERVICE)
    public CompletableFuture<Token> getTokenByUser(Credential credential) {
        return userRepository.getUser(credential)
            .thenCompose(s -> TokenRepository.getToken(s));
    }
}

@Repository
public class UserRepository {

    @Async(AsyncConfiguration.TASK_EXECUTOR_REPOSITORY)
    public CompletableFuture<User> getUser(Credential credentials) {
        return CompletableFuture.supplyAsync(() -> 
            new User(credentials.getUsername())
        );
    }       
}

@Repository
public class TokenRepository {

    @Async(AsyncConfiguration.TASK_EXECUTOR_REPOSITORY)
    public CompletableFuture<Token> getToken(User user) {
        return CompletableFuture.supplyAsync(() -> 
            new Token(user.getUserId())
        );
    }
}

前面的代码运行完美,但下面的代码不会异步运行,结果总是null.

@Service
public class AsyncServiceImpl {
    /** .. Init repository instances .. **/

    @Async(AsyncConfiguration.TASK_EXECUTOR_SERVICE)
    public CompletableFuture<Token> requestToken(Credential credential) {
        return CompletableFuture.supplyAsync(() -> userRepository.getUser(credential))
            .thenCompose(s -> 
                CompletableFuture.supplyAsync(() -> TokenRepository.getToken(s)));
    }
}

@Repository
public class UserRepository {
    @Async(AsyncConfiguration.TASK_EXECUTOR_REPOSITORY)
    public User getUser(Credential credentials) {
        return new User(credentials.getUsername());
    }       
}

@Repository
public class TokenRepository {
    @Async(AsyncConfiguration.TASK_EXECUTOR_SERVICE)
    public Token getToken(User user) {
        return new Token(user.getUserId());
    }
}

为什么第二个代码不起作用?

4

1 回答 1

2

根据Spring @Async Javadoc

返回类型被限制为void或者Future

并且在参考文档中也有进一步的详细说明

在最简单的情况下,注释可以应用于void返回方法。

[…]

甚至可以异步调用返回值的方法。但是,此类方法需要具有Future类型化的返回值。这仍然提供了异步执行的好处,以便调用者可以在调用get()该 Future 之前执行其他任务。

在您的第二个示例中,您的@Async-annotated 方法不返回 a Future(或者ListenableFutureCompletableFuture支持)。但是,Spring 必须异步运行您的方法。因此,它只能表现得好像您的方法具有void返回类型,因此它返回null.

附带说明一下,当您使用 时@Async,您的方法已经异步运行,因此您不应该CompletableFuture.supplyAsync()在方法内部使用。你应该简单地计算你的结果并返回它,CompletableFuture.completedFuture()如果需要的话。如果您的方法只是组成期货(例如您的服务只是组成异步存储库结果),那么您可能不需要@Async注释。另请参阅入门指南中的示例

于 2018-04-30T19:08:46.703 回答