Fix generic type result copy in InjvmInvoker (#13351)
This commit is contained in:
parent
5df704b67c
commit
a8b83823dc
|
|
@ -27,6 +27,7 @@ import org.apache.dubbo.remoting.utils.UrlUtils;
|
|||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_ERROR_DESERIALIZE;
|
||||
|
||||
|
|
@ -38,7 +39,7 @@ public class DefaultParamDeepCopyUtil implements ParamDeepCopyUtil {
|
|||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public <T> T copy(URL url, Object src, Class<T> targetClass) {
|
||||
public <T> T copy(URL url, Object src, Class<T> targetClass, Type type) {
|
||||
Serialization serialization = url.getOrDefaultFrameworkModel()
|
||||
.getExtensionLoader(Serialization.class)
|
||||
.getExtension(UrlUtils.serializationOrDefault(url));
|
||||
|
|
@ -50,7 +51,11 @@ public class DefaultParamDeepCopyUtil implements ParamDeepCopyUtil {
|
|||
|
||||
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray())) {
|
||||
ObjectInput objectInput = serialization.deserialize(url, inputStream);
|
||||
return objectInput.readObject(targetClass);
|
||||
if (type != null) {
|
||||
return objectInput.readObject(targetClass, type);
|
||||
} else {
|
||||
return objectInput.readObject(targetClass);
|
||||
}
|
||||
} catch (ClassNotFoundException | IOException e) {
|
||||
logger.error(PROTOCOL_ERROR_DESERIALIZE, "", "", "Unable to deep copy parameter to target class.", e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ public class InjvmInvoker<T> extends AbstractInvoker<T> {
|
|||
appResponse.setObjectAttachments(new HashMap<>(result.getObjectAttachments()));
|
||||
return appResponse;
|
||||
} else {
|
||||
rebuildValue(invocation, desc, result);
|
||||
rebuildValue(invocation, invoker, result);
|
||||
AppResponse appResponse = new AppResponse(result.getValue());
|
||||
appResponse.setObjectAttachments(new HashMap<>(result.getObjectAttachments()));
|
||||
return appResponse;
|
||||
|
|
@ -190,7 +190,7 @@ public class InjvmInvoker<T> extends AbstractInvoker<T> {
|
|||
if (r.hasException()) {
|
||||
rpcResult.setException(r.getException());
|
||||
} else {
|
||||
Object rebuildValue = rebuildValue(invocation, desc, r.getValue());
|
||||
Object rebuildValue = rebuildValue(invocation, invoker, r.getValue());
|
||||
rpcResult.setValue(rebuildValue);
|
||||
}
|
||||
}
|
||||
|
|
@ -201,7 +201,7 @@ public class InjvmInvoker<T> extends AbstractInvoker<T> {
|
|||
if (result.hasException()) {
|
||||
rpcResult.setException(result.getException());
|
||||
} else {
|
||||
Object rebuildValue = rebuildValue(invocation, desc, result.getValue());
|
||||
Object rebuildValue = rebuildValue(invocation, invoker, result.getValue());
|
||||
rpcResult.setValue(rebuildValue);
|
||||
}
|
||||
rpcResult.setObjectAttachments(new HashMap<>(result.getObjectAttachments()));
|
||||
|
|
@ -232,11 +232,7 @@ public class InjvmInvoker<T> extends AbstractInvoker<T> {
|
|||
}
|
||||
String methodName = invocation.getMethodName();
|
||||
|
||||
ServiceModel consumerServiceModel = invocation.getServiceModel();
|
||||
boolean shouldSkip = shouldIgnoreSameModule
|
||||
&& consumerServiceModel != null
|
||||
&& Objects.equals(providerServiceModel.getModuleModel(), consumerServiceModel.getModuleModel());
|
||||
if (CommonConstants.$INVOKE.equals(methodName) || shouldSkip) {
|
||||
if (isSkipCopy(invocation, invoker)) {
|
||||
// generic invoke, skip copy arguments
|
||||
RpcInvocation copiedInvocation = new RpcInvocation(
|
||||
invocation.getTargetServiceUniqueName(),
|
||||
|
|
@ -297,16 +293,43 @@ public class InjvmInvoker<T> extends AbstractInvoker<T> {
|
|||
}
|
||||
}
|
||||
|
||||
private Object rebuildValue(Invocation invocation, String desc, Object originValue) {
|
||||
private boolean isSkipCopy(Invocation invocation, Invoker<?> invoker) {
|
||||
ServiceModel providerServiceModel = invoker.getUrl().getServiceModel();
|
||||
|
||||
if (providerServiceModel == null) {
|
||||
return true;
|
||||
}
|
||||
String methodName = invocation.getMethodName();
|
||||
|
||||
ServiceModel consumerServiceModel = invocation.getServiceModel();
|
||||
boolean shouldSkip = shouldIgnoreSameModule
|
||||
&& consumerServiceModel != null
|
||||
&& Objects.equals(providerServiceModel.getModuleModel(), consumerServiceModel.getModuleModel());
|
||||
|
||||
return CommonConstants.$INVOKE.equals(methodName)
|
||||
|| CommonConstants.$INVOKE_ASYNC.equals(methodName)
|
||||
|| shouldSkip;
|
||||
}
|
||||
|
||||
private Object rebuildValue(Invocation invocation, Invoker<?> invoker, Object originValue) {
|
||||
if (isSkipCopy(invocation, invoker)) {
|
||||
return originValue;
|
||||
}
|
||||
|
||||
Object value = originValue;
|
||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
ServiceModel consumerServiceModel = getUrl().getServiceModel();
|
||||
if (consumerServiceModel != null) {
|
||||
Class<?> returnType = getReturnType(consumerServiceModel, invocation.getMethodName(), desc);
|
||||
if (returnType != null) {
|
||||
Thread.currentThread().setContextClassLoader(consumerServiceModel.getClassLoader());
|
||||
value = paramDeepCopyUtil.copy(consumerUrl, originValue, returnType);
|
||||
Thread.currentThread().setContextClassLoader(consumerServiceModel.getClassLoader());
|
||||
Type[] returnTypes = RpcUtils.getReturnTypes(invocation);
|
||||
if (returnTypes == null) {
|
||||
return originValue;
|
||||
}
|
||||
if (returnTypes.length == 1) {
|
||||
value = paramDeepCopyUtil.copy(consumerUrl, originValue, (Class<?>) returnTypes[0]);
|
||||
} else if (returnTypes.length == 2) {
|
||||
value = paramDeepCopyUtil.copy(consumerUrl, originValue, (Class<?>) returnTypes[0], returnTypes[1]);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
|
|
|
|||
|
|
@ -20,8 +20,14 @@ import org.apache.dubbo.common.URL;
|
|||
import org.apache.dubbo.common.extension.ExtensionScope;
|
||||
import org.apache.dubbo.common.extension.SPI;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
@SPI(scope = ExtensionScope.FRAMEWORK)
|
||||
public interface ParamDeepCopyUtil {
|
||||
|
||||
<T> T copy(URL url, Object src, Class<T> targetClass);
|
||||
default <T> T copy(URL url, Object src, Class<T> targetClass) {
|
||||
return copy(url, src, targetClass, null);
|
||||
}
|
||||
|
||||
<T> T copy(URL url, Object src, Class<T> targetClass, Type type);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue