Fix generic type result copy in InjvmInvoker (#13351)

This commit is contained in:
Albumen Kevin 2023-11-16 15:56:25 +08:00 committed by GitHub
parent 5df704b67c
commit a8b83823dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 16 deletions

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}