异步 Spring 使用 Kotlin 启动不工作

Async Spring Boot using Kotlin not working

我正在尝试创建一个 Spring 异步执行操作的服务和 returns ListenableFuture。我希望在操作失败时触发失败回调 - 我尝试这样做是使用 AsyncResult.forExecutionException 如下所示:

@Service
open class UserClientService {

    @Async
    fun fetchUser(email: String): ListenableFuture<User> {
        val uri = buildUri(email)
        val headers = buildHeaders()
        try {
            val result = restTemplate.exchange(uri, HttpMethod.GET, HttpEntity<Any>(headers), User::class.java)
            return AsyncResult.forValue(result.body)
        } catch (e: RestClientException) {
            return AsyncResult.forExecutionException(e)
        }
    }
}

入口点:

@SpringBootApplication
@EnableAsync
open class UserProxyApplication

fun main(args: Array<String>) {
    SpringApplication.run(UserProxyApplication::class.java, *args)
} 

SpringRestController实现如下:

@RestController
@RequestMapping("/users")
class UserController @Autowired constructor(
        val client: UserClientService
) {
    @RequestMapping(method = arrayOf(RequestMethod.GET))
    fun getUser(@RequestParam(value = "email") email: String): DeferredResult<ResponseEntity<User>> {
        val result = DeferredResult<ResponseEntity<User>>(TimeUnit.SECONDS.toMillis(10))
        client.fetchUser(email).addCallback(
                { success -> result.setResult(ResponseEntity.ok(success)) },
                { failure -> result.setResult(ResponseEntity(HttpStatus.NOT_FOUND)) }
        )
        return result;
    }
}

问题 是当 UserClientService REST 调用中抛出异常时从未触发 UserController 中的失败回调。相反,成功回调是通过 success 参数为 null 触发的。

在 Kotlin 中,我可以使用 success!! 检查 success 是否为 null - 这会抛出一个异常,然后 确实 使用 failure 触发失败回调参数是 NPE。

问题UserClientService异常时如何触发UserController的失败回调?

更新 A 似乎一切都在同一个线程上执行 "http-nio-8080-exec-XXX" 不管我是否使用 @Async -- 见评论。

这一切都有效,如果:

A) 方法 fetchUser 被声明为 open,即不是最终方法,因此 Spring 可以代理调用

...或...

B) 你创建一个接口 IUserClientService 并在 UserController:

的构造函数中使用它
interface IUserClientService {
    fun fetchUser(email: String): ListenableFuture<User>
}

现在 UserClientService 实现接口:

@Service
open class UserClientService : IUserClientService {

    @Async
    override fun fetchUser(email: String): ListenableFuture<User> {
// ... rest as shown in question ...

最后 UserController:

@RestController
@RequestMapping("/users")
class UserController @Autowired constructor(
    val client: IUserClientService
) {
    @RequestMapping(method = arrayOf(RequestMethod.GET))
    fun getUser(@RequestParam(value = "email") email: String): DeferredResult<ResponseEntity<User>> {
// ... rest as shown in question ...

不确定这是不是因为我使用的是 Kotlin。我看到的示例不需要实现接口。