diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java index 0506d762b2..f62a16a71e 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java @@ -29,6 +29,8 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; @@ -207,20 +209,41 @@ public abstract class AbstractServiceRestMetadataResolver implements ServiceRest sort(declaredServiceMethods, MethodComparator.INSTANCE); sort(serviceMethods, MethodComparator.INSTANCE); + // prevent from repeat method (impl proxy) & leaving out method(interface proxy) + HashSet methodComparators = new HashSet<>(); + + // TODO Map key: method desc & value: Set for accelerate loop speed for (Method declaredServiceMethod : declaredServiceMethods) { for (Method serviceMethod : serviceMethods) { - if (overrides(serviceMethod, declaredServiceMethod)) { - serviceMethodsMap.put(serviceMethod, declaredServiceMethod); - // override method count > 1 - // // once method match ,break for decrease loop times - // break; + + if (!overrides(serviceMethod, declaredServiceMethod)) { + continue; } + + String methodDesc = getMethodDesc(serviceMethod); + + if (!methodComparators.add(methodDesc)) { + continue; + } + + serviceMethodsMap.put(serviceMethod, declaredServiceMethod); } } + // make them to be read-only return unmodifiableMap(serviceMethodsMap); } + /** + * For simple method desc + * + * @param serviceMethod + * @return + */ + private String getMethodDesc(Method serviceMethod) { + return serviceMethod.getName() + Arrays.toString(serviceMethod.getParameterTypes()); + } + private void putServiceMethodToMap(Map serviceMethodsMap, List declaredServiceMethods) { declaredServiceMethods.stream().forEach(method -> { diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/SpringMvcRestProtocolTest.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/SpringMvcRestProtocolTest.java index 478b0b39be..5eee6f267b 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/SpringMvcRestProtocolTest.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/SpringMvcRestProtocolTest.java @@ -47,6 +47,9 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.springframework.aop.framework.AdvisedSupport; +import org.springframework.aop.framework.AopProxy; +import org.springframework.aop.framework.ProxyCreatorSupport; import org.springframework.util.LinkedMultiValueMap; import static org.apache.dubbo.remoting.Constants.SERVER_KEY; @@ -393,6 +396,35 @@ public class SpringMvcRestProtocolTest { exporter.unexport(); } + @Test + void testProxyDoubleCheck() { + + ProxyCreatorSupport proxyCreatorSupport = new ProxyCreatorSupport(); + AdvisedSupport advisedSupport = new AdvisedSupport(); + advisedSupport.setTarget(getServerImpl()); + AopProxy aopProxy = proxyCreatorSupport.getAopProxyFactory().createAopProxy(advisedSupport); + Object proxy = aopProxy.getProxy(); + SpringRestDemoService server = (SpringRestDemoService) proxy; + + URL nettyUrl = this.registerProvider(exportUrl, server, SpringRestDemoService.class); + + Exporter exporter = getExport(nettyUrl, server); + + SpringRestDemoService demoService = this.proxy.getProxy(protocol.refer(SpringRestDemoService.class, nettyUrl)); + + Integer result = demoService.primitiveInt(1, 2); + Long resultLong = demoService.primitiveLong(1, 2l); + long resultByte = demoService.primitiveByte((byte) 1, 2l); + long resultShort = demoService.primitiveShort((short) 1, 2l, 1); + + assertThat(result, is(3)); + assertThat(resultShort, is(3l)); + assertThat(resultLong, is(3l)); + assertThat(resultByte, is(3l)); + + exporter.unexport(); + } + public static class TestExceptionMapper implements ExceptionHandler { @Override