spring4-3 适配jdk8的CompletableFuture

1.DeferredResultMethodReturnValueHandler

旧版本(<4.3)

@Override
	public void handleReturnValue(Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {

		if (returnValue == null) {
			mavContainer.setRequestHandled(true);
			return;
		}

		DeferredResult<?> deferredResult = (DeferredResult<?>) returnValue;
		WebAsyncUtils.getAsyncManager(webRequest).startDeferredResultProcessing(deferredResult, mavContainer);
	}

新版本(≥4.3)

@Override
	public void handleReturnValue(Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {

		if (returnValue == null) {
			mavContainer.setRequestHandled(true);
			return;
		}

		DeferredResultAdapter adapter = getAdapterFor(returnValue.getClass());
		if (adapter == null) {
			throw new IllegalStateException(
					"Could not find DeferredResultAdapter for return value type: " + returnValue.getClass());
		}
		DeferredResult<?> result = adapter.adaptToDeferredResult(returnValue);
		WebAsyncUtils.getAsyncManager(webRequest).startDeferredResultProcessing(result, mavContainer);
	}

这里面添加了对CompletionStage(CompletableFuture)的特殊处理,即将CompletableFuture适配为DeferredResult

@UsesJava8
	private static class CompletionStageAdapter implements DeferredResultAdapter {

		@Override
		public DeferredResult<?> adaptToDeferredResult(Object returnValue) {
			Assert.isInstanceOf(CompletionStage.class, returnValue, "CompletionStage expected");
			final DeferredResult<Object> result = new DeferredResult<Object>();
			@SuppressWarnings("unchecked")
			CompletionStage<?> future = (CompletionStage<?>) returnValue;
			future.handle(new BiFunction<Object, Throwable, Object>() {
				@Override
				public Object apply(Object value, Throwable ex) {
					if (ex != null) {
						result.setErrorResult(ex);
					}
					else {
						result.setResult(value);
					}
					return null;
				}
			});
			return result;
		}
	}

但是这里面就会模糊掉(牺牲掉)DeferredResult里面原来有的超时/完成回调这部分的功能。

更新版本(≥5.0)

实现没有变化,只是干掉了adapter接口

else if (returnValue instanceof CompletionStage) {
			result = adaptCompletionStage((CompletionStage<?>) returnValue);
		}
private DeferredResult<Object> adaptCompletionStage(CompletionStage<?> future) {
		DeferredResult<Object> result = new DeferredResult<>();
		future.handle((BiFunction<Object, Throwable, Object>) (value, ex) -> {
			if (ex != null) {
				result.setErrorResult(ex);
			}
			else {
				result.setResult(value);
			}
			return null;
		});
		return result;
	}

2.spring原生代码

4.3.x增加了对CompletionStage返回值的处理:

5.0.x删除了DeferredResultAdapter这个接口:

经验分享 程序员 微信小程序 职场和发展