diff --git a/src/main/java/org/redkale/boot/NodeServer.java b/src/main/java/org/redkale/boot/NodeServer.java index c586b907f..1c707e4c9 100644 --- a/src/main/java/org/redkale/boot/NodeServer.java +++ b/src/main/java/org/redkale/boot/NodeServer.java @@ -489,7 +489,7 @@ public abstract class NodeServer { } final ResourceTypeLoader resourceLoader = (ResourceFactory rf, String srcResourceName, final Object srcObj, final String resourceName, Field field, final Object attachment) -> { try { - if (SncpClient.parseMethod(serviceImplClass).isEmpty() + if (SncpClient.parseMethodActions(serviceImplClass).isEmpty() && (serviceImplClass.getAnnotation(Priority.class) == null && serviceImplClass.getAnnotation(javax.annotation.Priority.class) == null)) { //class没有可用的方法且没有标记启动优先级的, 通常为BaseService if (!serviceImplClass.getName().startsWith("org.redkale.") && !serviceImplClass.getSimpleName().contains("Base")) { logger.log(Level.FINE, serviceImplClass + " cannot load because not found less one public non-final method"); diff --git a/src/main/java/org/redkale/net/sncp/Sncp.java b/src/main/java/org/redkale/net/sncp/Sncp.java index d80f0be6e..7cd64280e 100644 --- a/src/main/java/org/redkale/net/sncp/Sncp.java +++ b/src/main/java/org/redkale/net/sncp/Sncp.java @@ -57,10 +57,18 @@ public abstract class Sncp { private Sncp() { } + public static Uint128 actionid(final RpcAction action) { + return hash(action.name()); + } + public static Uint128 actionid(final java.lang.reflect.Method method) { if (method == null) { return Uint128.ZERO; } + RpcAction action = method.getAnnotation(RpcAction.class); + if (action != null) { + return hash(action.name()); + } StringBuilder sb = new StringBuilder(); //不能使用method.toString() 因为包含declaringClass信息导致接口与实现类的方法hash不一致 sb.append(method.getReturnType().getName()).append(' '); sb.append(method.getName()); diff --git a/src/main/java/org/redkale/net/sncp/SncpClient.java b/src/main/java/org/redkale/net/sncp/SncpClient.java index eafd461a9..83e6714f0 100644 --- a/src/main/java/org/redkale/net/sncp/SncpClient.java +++ b/src/main/java/org/redkale/net/sncp/SncpClient.java @@ -87,8 +87,8 @@ public final class SncpClient { this.serviceid = Sncp.serviceid(serviceResourceName, serviceResourceType); final List methodens = new ArrayList<>(); //------------------------------------------------------------------------------ - for (java.lang.reflect.Method method : parseMethod(serviceClass)) { - methodens.add(new SncpAction(serviceClass, method, Sncp.actionid(method))); + for (Map.Entry en : parseMethodActions(serviceClass).entrySet()) { + methodens.add(new SncpAction(serviceClass, en.getValue(), en.getKey())); } this.actions = methodens.toArray(new SncpAction[methodens.size()]); this.addrBytes = clientSncpAddress == null ? new byte[4] : clientSncpAddress.getAddress().getAddress(); @@ -101,8 +101,8 @@ public final class SncpClient { static List getSncpActions(final Class serviceClass) { final List actions = new ArrayList<>(); //------------------------------------------------------------------------------ - for (java.lang.reflect.Method method : parseMethod(serviceClass)) { - actions.add(new SncpAction(serviceClass, method, Sncp.actionid(method))); + for (Map.Entry en : parseMethodActions(serviceClass).entrySet()) { + actions.add(new SncpAction(serviceClass, en.getValue(), en.getKey())); } return actions; } @@ -170,10 +170,10 @@ public final class SncpClient { + ", actions.size = " + actions.length + ")"; } - public static List parseMethod(final Class serviceClass) { + public static LinkedHashMap parseMethodActions(final Class serviceClass) { final List list = new ArrayList<>(); final List multis = new ArrayList<>(); - final Map actionids = new HashMap<>(); + final Map actionids = new LinkedHashMap<>(); for (final java.lang.reflect.Method method : serviceClass.getMethods()) { if (method.isSynthetic()) { continue; @@ -201,7 +201,6 @@ public final class SncpClient { continue; } } - //if (onlySncpDyn && method.getAnnotation(SncpDyn.class) == null) continue; Uint128 actionid = Sncp.actionid(method); Method old = actionids.get(actionid); @@ -230,7 +229,16 @@ public final class SncpClient { }); //带SncpDyn必须排在前面 multis.addAll(list); - return multis; + final LinkedHashMap rs = new LinkedHashMap<>(); + for (Method method : multis) { + for (Map.Entry en : actionids.entrySet()) { + if (en.getValue() == method) { + rs.put(en.getKey(), en.getValue()); + break; + } + } + } + return rs; } //只给远程模式调用的 @@ -597,18 +605,6 @@ public final class SncpClient { tpoicAddrIndex = i; } } - for (Annotation ann : anns[i]) { - if (ann.annotationType() == RpcCall.class) { - try { - atts[i + 1] = ((RpcCall) ann).value().getDeclaredConstructor().newInstance(); - RedkaleClassLoader.putReflectionDeclaredConstructors(((RpcCall) ann).value(), ((RpcCall) ann).value().getName()); - hasattr = true; - } catch (Exception e) { - logger.log(Level.SEVERE, RpcCall.class.getSimpleName() + ".attribute cannot a newInstance for" + method, e); - } - break; - } - } } } } diff --git a/src/main/java/org/redkale/net/sncp/SncpDynServlet.java b/src/main/java/org/redkale/net/sncp/SncpDynServlet.java index 592bbdb88..e0e17af50 100644 --- a/src/main/java/org/redkale/net/sncp/SncpDynServlet.java +++ b/src/main/java/org/redkale/net/sncp/SncpDynServlet.java @@ -6,7 +6,6 @@ package org.redkale.net.sncp; import java.io.IOException; -import java.lang.annotation.Annotation; import java.lang.reflect.*; import java.nio.channels.CompletionHandler; import java.util.*; @@ -21,7 +20,7 @@ import org.redkale.asm.Type; import org.redkale.convert.bson.*; import org.redkale.net.sncp.SncpAsyncHandler.DefaultSncpAsyncHandler; import static org.redkale.net.sncp.SncpRequest.DEFAULT_HEADER; -import org.redkale.service.*; +import org.redkale.service.Service; import org.redkale.util.*; /** @@ -49,49 +48,16 @@ public final class SncpDynServlet extends SncpServlet { this.maxTypeLength = maxTypeLength; this.maxNameLength = maxNameLength; this.serviceid = Sncp.serviceid(serviceResourceName, serviceResourceType); - Set actionids = new HashSet<>(); RedkaleClassLoader.putReflectionPublicMethods(service.getClass().getName()); - for (java.lang.reflect.Method method : service.getClass().getMethods()) { - if (method.isSynthetic()) { - continue; - } - if (Modifier.isStatic(method.getModifiers())) { - continue; - } - if (Modifier.isFinal(method.getModifiers())) { - continue; - } - if (method.getAnnotation(Local.class) != null) { - continue; - } - if (method.getName().equals("getClass") || method.getName().equals("toString")) { - continue; - } - if (method.getName().equals("equals") || method.getName().equals("hashCode")) { - continue; - } - if (method.getName().equals("notify") || method.getName().equals("notifyAll") || method.getName().equals("wait")) { - continue; - } - if (method.getParameterCount() == 1 && method.getParameterTypes()[0] == AnyValue.class) { - if (method.getName().equals("init") || method.getName().equals("stop") || method.getName().equals("destroy")) { - continue; - } - } - - final Uint128 actionid = Sncp.actionid(method); + for (Map.Entry en : SncpClient.parseMethodActions(service.getClass()).entrySet()) { SncpServletAction action; try { - action = SncpServletAction.create(service, actionid, method); + action = SncpServletAction.create(service, en.getKey(), en.getValue()); } catch (RuntimeException e) { - throw new SncpException(method + " create " + SncpServletAction.class.getSimpleName() + " error", e); + throw new SncpException(en.getValue() + " create " + SncpServletAction.class.getSimpleName() + " error", e); } action.convert = convert; - if (actionids.contains(actionid)) { - throw new SncpException(type.getName() + " have action(Method=" + method + ", actionid=" + actionid + ") same to (" + actions.get(actionid).method + ")"); - } - actions.put(actionid, action); - actionids.add(actionid); + actions.put(en.getKey(), action); } maxNameLength.set(Math.max(maxNameLength.get(), serviceResourceName.length() + 1)); maxTypeLength.set(Math.max(maxTypeLength.get(), type.getName().length())); @@ -662,29 +628,6 @@ public final class SncpDynServlet extends SncpServlet { instance.handlerFuncParamIndex = handlerFuncIndex; instance.handlerFuncParamClass = handlerFuncClass; instance.boolReturnTypeFuture = boolReturnTypeFuture; - - org.redkale.util.Attribute[] atts = new org.redkale.util.Attribute[originalParamTypes.length + 1]; - Annotation[][] anns = method.getParameterAnnotations(); - boolean hasattr = false; - for (int i = 0; i < anns.length; i++) { - if (anns[i].length > 0) { - for (Annotation ann : anns[i]) { - if (ann.annotationType() == RpcCall.class) { - try { - atts[i + 1] = ((RpcCall) ann).value().getDeclaredConstructor().newInstance(); - RedkaleClassLoader.putReflectionDeclaredConstructors(((RpcCall) ann).value(), ((RpcCall) ann).value().getName()); - hasattr = true; - } catch (Exception e) { - logger.log(Level.SEVERE, RpcCall.class.getSimpleName() + ".attribute cannot a newInstance for" + method, e); - } - break; - } - } - } - } - if (hasattr) { - instance.paramAttrs = atts; - } newClazz.getField("service").set(instance, service); return instance; } catch (Exception ex) { diff --git a/src/main/java/org/redkale/service/RpcAction.java b/src/main/java/org/redkale/service/RpcAction.java new file mode 100644 index 000000000..024ba7b52 --- /dev/null +++ b/src/main/java/org/redkale/service/RpcAction.java @@ -0,0 +1,26 @@ +/* + * + */ +package org.redkale.service; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.lang.annotation.*; + +/** + * 用于自定义SncpActionid,默认会根据Method.toString来计算actionid + * + *

+ * 详情见: https://redkale.org + * + * @author zhangjx + * @since 2.8.0 + */ +@Inherited +@Documented +@Target({METHOD}) +@Retention(RUNTIME) +public @interface RpcAction { + + String name(); +} diff --git a/src/main/java/org/redkale/service/RpcCall.java b/src/main/java/org/redkale/service/RpcCall.java deleted file mode 100644 index b2aa7a6d4..000000000 --- a/src/main/java/org/redkale/service/RpcCall.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkale.service; - -import java.lang.annotation.*; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import org.redkale.util.*; - -/** - * 参数回写, 当Service的方法需要更改参数对象内部的数据时,需要使用RpcCall - * - *

详情见: https://redkale.org - * @author zhangjx - */ -@Inherited -@Documented -@Target({ElementType.PARAMETER}) -@Retention(RUNTIME) -public @interface RpcCall { - - Class value(); -} diff --git a/src/main/java/org/redkale/service/RpcCallArrayAttribute.java b/src/main/java/org/redkale/service/RpcCallArrayAttribute.java deleted file mode 100644 index 80c263322..000000000 --- a/src/main/java/org/redkale/service/RpcCallArrayAttribute.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkale.service; - -import java.io.Serializable; -import java.lang.reflect.Array; -import org.redkale.util.Attribute; - -/** - * - *

- * 详情见: https://redkale.org - * - * @author zhangjx - * - * @since 2.1.0 - * @param 对象类型 - * @param 字段类型 - */ -@SuppressWarnings("unchecked") -public class RpcCallArrayAttribute implements Attribute { - - public static final RpcCallArrayAttribute instance = new RpcCallArrayAttribute(); - - @Override - public Class type() { - return (Class) Object.class; - } - - @Override - public Class declaringClass() { - return (Class) (Class) Object[].class; - } - - @Override - public String field() { - return ""; - } - - @Override - public F get(final T[] objs) { - if (objs == null || objs.length == 0) { - return null; - } - final Attribute attr = RpcCallAttribute.load(objs[0].getClass()); - final Object keys = Array.newInstance(attr.type(), objs.length); - for (int i = 0; i < objs.length; i++) { - Array.set(keys, i, attr.get(objs[i])); - } - return (F) keys; - } - - @Override - public void set(final T[] objs, final F keys) { - if (objs == null || objs.length == 0) { - return; - } - final Attribute attr = RpcCallAttribute.load(objs[0].getClass()); - for (int i = 0; i < objs.length; i++) { - attr.set(objs[i], (Serializable) Array.get(keys, i)); - } - } - -} diff --git a/src/main/java/org/redkale/service/RpcCallAttribute.java b/src/main/java/org/redkale/service/RpcCallAttribute.java deleted file mode 100644 index 8613207f1..000000000 --- a/src/main/java/org/redkale/service/RpcCallAttribute.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkale.service; - -import java.io.Serializable; -import java.lang.reflect.Field; -import java.util.concurrent.ConcurrentHashMap; -import org.redkale.util.Attribute; - -/** - * - *

- * 详情见: https://redkale.org - * - * @author zhangjx - * - * @since 2.1.0 - */ -public class RpcCallAttribute implements Attribute { - - public static final RpcCallAttribute instance = new RpcCallAttribute(); - - private static final ConcurrentHashMap attributes = new ConcurrentHashMap<>(); - - static Attribute load(final Class clazz) { - Attribute rs = attributes.get(clazz); - if (rs != null) { - return rs; - } - synchronized (attributes) { - rs = attributes.get(clazz); - if (rs == null) { - Class cltmp = clazz; - do { - for (Field field : cltmp.getDeclaredFields()) { - try { - rs = Attribute.create(cltmp, field); - attributes.put(clazz, rs); - return rs; - } catch (RuntimeException e) { - } - } - } while ((cltmp = cltmp.getSuperclass()) != Object.class); - } - return rs; - } - } - - @Override - public Class type() { - return Serializable.class; - } - - @Override - public Class declaringClass() { - return Object.class; - } - - @Override - public String field() { - return ""; - } - - @Override - public Serializable get(final Object obj) { - if (obj == null) { - return null; - } - return load(obj.getClass()).get(obj); - } - - @Override - public void set(final Object obj, final Serializable key) { - if (obj == null) { - return; - } - load(obj.getClass()).set(obj, key); - } - -} diff --git a/src/test/java/org/redkale/test/sncp/SncpTestIService.java b/src/test/java/org/redkale/test/sncp/SncpTestIService.java index 737cb991a..098358227 100644 --- a/src/test/java/org/redkale/test/sncp/SncpTestIService.java +++ b/src/test/java/org/redkale/test/sncp/SncpTestIService.java @@ -6,7 +6,7 @@ package org.redkale.test.sncp; import java.util.concurrent.CompletableFuture; -import org.redkale.service.*; +import org.redkale.service.Service; /** * @@ -22,7 +22,7 @@ public interface SncpTestIService extends Service { public CompletableFuture queryResultAsync(SncpTestBean bean); - public void insert(@RpcCall(RpcCallArrayAttribute.class) SncpTestBean... beans); + public void insert(SncpTestBean... beans); - public String updateBean(@RpcCall(SncpTestServiceImpl.CallAttribute.class) SncpTestBean bean); + public String updateBean(SncpTestBean bean); } diff --git a/src/test/java/org/redkale/test/sncp/SncpTestServiceImpl.java b/src/test/java/org/redkale/test/sncp/SncpTestServiceImpl.java index 42194be25..354cdcaa9 100644 --- a/src/test/java/org/redkale/test/sncp/SncpTestServiceImpl.java +++ b/src/test/java/org/redkale/test/sncp/SncpTestServiceImpl.java @@ -8,8 +8,7 @@ package org.redkale.test.sncp; import java.lang.reflect.Method; import java.net.InetSocketAddress; import java.nio.channels.CompletionHandler; -import java.util.concurrent.*; - +import java.util.concurrent.CompletableFuture; import org.redkale.annotation.ResourceType; import org.redkale.net.*; import org.redkale.net.sncp.*; @@ -84,7 +83,7 @@ public class SncpTestServiceImpl implements SncpTestIService { } @Override - public void insert(@RpcCall(RpcCallArrayAttribute.class) SncpTestBean... beans) { + public void insert(SncpTestBean... beans) { for (SncpTestBean bean : beans) { bean.setId(System.currentTimeMillis()); } @@ -98,11 +97,13 @@ public class SncpTestServiceImpl implements SncpTestIService { public void queryResult(CompletionHandler handler, @RpcAttachment SncpTestBean bean) { System.out.println(Thread.currentThread().getName() + " handler 运行了queryResult方法"); - if (handler != null) handler.completed("result: " + bean, bean); + if (handler != null) { + handler.completed("result: " + bean, bean); + } } @Override - public String updateBean(@RpcCall(CallAttribute.class) SncpTestBean bean) { + public String updateBean(SncpTestBean bean) { bean.setId(System.currentTimeMillis()); System.out.println(Thread.currentThread().getName() + " 运行了updateBean方法"); return "result: " + bean; @@ -120,7 +121,7 @@ public class SncpTestServiceImpl implements SncpTestIService { System.out.println(method); } System.out.println("-----------------------------------"); - for (Method method : SncpClient.parseMethod(service.getClass())) { + for (Method method : SncpClient.parseMethodActions(service.getClass()).values()) { System.out.println(method); } System.out.println("-----------------------------------"); @@ -129,7 +130,7 @@ public class SncpTestServiceImpl implements SncpTestIService { System.out.println(method); } System.out.println("-----------------------------------"); - for (Method method : SncpClient.parseMethod(service.getClass())) { + for (Method method : SncpClient.parseMethodActions(service.getClass()).values()) { System.out.println(method); } System.out.println("-----------------------------------"); @@ -138,7 +139,7 @@ public class SncpTestServiceImpl implements SncpTestIService { System.out.println(method); } System.out.println("-----------------------------------"); - for (Method method : SncpClient.parseMethod(service.getClass())) { + for (Method method : SncpClient.parseMethodActions(service.getClass()).values()) { System.out.println(method); } System.out.println("-----------------------------------");