diff --git a/src/org/redkale/boot/NodeHttpServer.java b/src/org/redkale/boot/NodeHttpServer.java index d6c9ab33b..561ee1de2 100644 --- a/src/org/redkale/boot/NodeHttpServer.java +++ b/src/org/redkale/boot/NodeHttpServer.java @@ -74,7 +74,7 @@ public class NodeHttpServer extends NodeServer { synchronized (regFactory) { Service nodeService = (Service) rf.find(resourceName, WebSocketNode.class); if (nodeService == null) { - nodeService = Sncp.createLocalService(resourceName, getExecutor(), application.getResourceFactory(), WebSocketNodeService.class, (InetSocketAddress) null, (Transport) null, (Collection) null); + nodeService = Sncp.createLocalService(resourceName, getExecutor(), application.getResourceFactory(), WebSocketNodeService.class, (InetSocketAddress) null, (String) null, (Set) null, (AnyValue) null, (Transport) null, (Collection) null); regFactory.register(resourceName, WebSocketNode.class, nodeService); resourceFactory.inject(nodeService, self); logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + nodeService); @@ -124,9 +124,9 @@ public class NodeHttpServer extends NodeServer { ss.add(new AbstractMap.SimpleEntry<>(clazz.getName(), mappings)); } } + int max = 0; if (ss != null && sb != null) { Collections.sort(ss, (AbstractMap.SimpleEntry o1, AbstractMap.SimpleEntry o2) -> o1.getKey().compareTo(o2.getKey())); - int max = 0; for (AbstractMap.SimpleEntry as : ss) { if (as.getKey().length() > max) max = as.getKey().length(); } @@ -138,18 +138,17 @@ public class NodeHttpServer extends NodeServer { sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR); } } - if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString()); if (rest && serverConf != null) { for (AnyValue restConf : serverConf.getAnyValues("rest")) { - loadRestServlet(prefix, restConf); + loadRestServlet(prefix, restConf, sb); } } + if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString()); } - protected void loadRestServlet(final String prefix, final AnyValue restConf) throws Exception { + protected void loadRestServlet(final String prefix, final AnyValue restConf, final StringBuilder sb) throws Exception { if (!rest) return; if (restConf == null) return; //不存在REST服务 - final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null; final String threadName = "[" + Thread.currentThread().getName() + "] "; final List> ss = sb == null ? null : new ArrayList<>(); @@ -170,8 +169,9 @@ public class NodeHttpServer extends NodeServer { final ClassFilter restFilter = ClassFilter.create(restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues); - super.interceptorServiceWrappers.forEach((wrapper) -> { - final Class stype = wrapper.getType(); + super.interceptorServices.forEach((service) -> { + final Class stype = Sncp.getServiceType(service); + final String name = Sncp.getResourceName(service); RestService rs = (RestService) stype.getAnnotation(RestService.class); if (rs != null && rs.ignore()) return; if (mustsign && rs == null) return; @@ -181,17 +181,15 @@ public class NodeHttpServer extends NodeServer { if (!autoload && !includeValues.contains(stypename)) return; if (!restFilter.accept(stypename)) return; - RestHttpServlet servlet = httpServer.addRestServlet(wrapper.getName(), stype, wrapper.getService(), baseServletClass, prefix, (AnyValue) null); + RestHttpServlet servlet = httpServer.addRestServlet(name, stype, service, baseServletClass, prefix, (AnyValue) null); resourceFactory.inject(servlet, NodeHttpServer.this); - if (finest) logger.finest("Create RestServlet[resource=" + wrapper.getName() + "] = " + servlet); + if (finest) logger.finest(threadName + " Create RestServlet(resource.name='" + name + "') = " + servlet); if (ss != null) { String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value(); for (int i = 0; i < mappings.length; i++) { mappings[i] = prefix + mappings[i]; } - if (servlet.getClass().getSimpleName().charAt(0) != '_') { - ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName(), mappings)); - } + ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName(), mappings)); } }); //输出信息 @@ -201,6 +199,7 @@ public class NodeHttpServer extends NodeServer { for (AbstractMap.SimpleEntry as : ss) { if (as.getKey().length() > max) max = as.getKey().length(); } + sb.append(threadName).append(" ").append(LINE_SEPARATOR); for (AbstractMap.SimpleEntry as : ss) { sb.append(threadName).append(" Load ").append(as.getKey()); for (int i = 0; i < max - as.getKey().length(); i++) { @@ -209,6 +208,5 @@ public class NodeHttpServer extends NodeServer { sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR); } } - if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString()); } } diff --git a/src/org/redkale/boot/NodeInterceptor.java b/src/org/redkale/boot/NodeInterceptor.java index 91a95ce10..a6edf764b 100644 --- a/src/org/redkale/boot/NodeInterceptor.java +++ b/src/org/redkale/boot/NodeInterceptor.java @@ -5,9 +5,6 @@ */ package org.redkale.boot; -import java.util.Objects; -import org.redkale.service.Service; - /** * NodeServer的拦截类 * @@ -38,63 +35,4 @@ public class NodeInterceptor { } - public static class InterceptorServiceWrapper { - - private String name; - - private Class type; - - private T service; - - public InterceptorServiceWrapper() { - } - - public InterceptorServiceWrapper(String name, Class type, T service) { - this.name = name; - this.type = type; - this.service = service; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Class getType() { - return type; - } - - public void setType(Class type) { - this.type = type; - } - - public T getService() { - return service; - } - - public void setService(T service) { - this.service = service; - } - - @Override - public int hashCode() { - int hash = 7; - hash = 97 * hash + Objects.hashCode(this.name); - hash = 97 * hash + Objects.hashCode(this.type); - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - final InterceptorServiceWrapper other = (InterceptorServiceWrapper) obj; - return Objects.equals(this.name, other.name) && Objects.equals(this.type, other.type); - } - - } } diff --git a/src/org/redkale/boot/NodeServer.java b/src/org/redkale/boot/NodeServer.java index 24d45aeae..579c9dbc5 100644 --- a/src/org/redkale/boot/NodeServer.java +++ b/src/org/redkale/boot/NodeServer.java @@ -69,7 +69,7 @@ public abstract class NodeServer { private InetSocketAddress sncpAddress; //加载Service时的处理函数 - protected Consumer consumer; + protected Consumer consumer; //server节点的配置 protected AnyValue serverConf; @@ -78,13 +78,17 @@ public abstract class NodeServer { protected NodeInterceptor interceptor; //供interceptor使用的Service对象集合 - protected final Set interceptorServiceWrappers = new LinkedHashSet<>(); + protected final Set interceptorServices = new LinkedHashSet<>(); //本地模式的Service对象集合 - protected final Set localServiceWrappers = new LinkedHashSet<>(); + protected final Set localServices = new LinkedHashSet<>(); //远程模式的Service对象集合 - protected final Set remoteServiceWrappers = new LinkedHashSet<>(); + protected final Set remoteServices = new LinkedHashSet<>(); + + private volatile int maxClassNameLength = 0; + + private volatile int maxNameLength = 0; public NodeServer(Application application, Server server) { this.application = application; @@ -228,16 +232,15 @@ public abstract class NodeServer { Transport sameGroupTransport = Sncp.getSameGroupTransport((Service) src); List diffGroupTransports = Arrays.asList(Sncp.getDiffGroupTransports((Service) src)); final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress(); - if ((src instanceof DataSource) && sncpAddr != null && resourceFactory.find(resourceName, DataCacheListener.class) == null) { //只有DataSourceService 才能赋值 DataCacheListener - Service cacheListenerService = Sncp.createLocalService(resourceName, getExecutor(), appResFactory, DataCacheListenerService.class, sncpAddr, sameGroupTransport, diffGroupTransports); - appResFactory.register(resourceName, DataCacheListener.class, cacheListenerService); + if ((src instanceof DataSource) && sncpAddr != null && resourceFactory.find(resourceName, DataCacheListener.class) == null) { //只有DataSourceService 才能赋值 DataCacheListener final NodeSncpServer sncpServer = application.findNodeSncpServer(sncpAddr); Set gs = application.findSncpGroups(sameGroupTransport, diffGroupTransports); - ServiceWrapper wrapper = new ServiceWrapper(DataCacheListenerService.class, cacheListenerService, resourceName, sncpServer.getSncpGroup(), gs, null); - localServiceWrappers.add(wrapper); - sncpServer.consumerAccept(wrapper); + Service cacheListenerService = Sncp.createLocalService(resourceName, getExecutor(), appResFactory, DataCacheListenerService.class, sncpAddr, sncpServer.getSncpGroup(), gs, Sncp.getConf((Service) src), sameGroupTransport, diffGroupTransports); + appResFactory.register(resourceName, DataCacheListener.class, cacheListenerService); + localServices.add(cacheListenerService); + sncpServer.consumerAccept(cacheListenerService); rf.inject(cacheListenerService, self); - logger.info("[" + Thread.currentThread().getName() + "] Load Service " + wrapper.getService()); + logger.info("[" + Thread.currentThread().getName() + "] Load Service " + cacheListenerService); } field.set(src, source); rf.inject(source, self); // 给其可能包含@Resource的字段赋值; @@ -251,13 +254,13 @@ public abstract class NodeServer { try { if (field.getAnnotation(Resource.class) == null) return; if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不需要注入 CacheSource - - SncpClient client = Sncp.getSncpClient((Service) src); - Transport sameGroupTransport = Sncp.getSameGroupTransport((Service) src); + final Service srcService = (Service) src; + SncpClient client = Sncp.getSncpClient(srcService); + Transport sameGroupTransport = Sncp.getSameGroupTransport(srcService); Transport[] dts = Sncp.getDiffGroupTransports((Service) src); List diffGroupTransports = dts == null ? new ArrayList<>() : Arrays.asList(dts); final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress(); - final CacheMemorySource source = Sncp.createLocalService(resourceName, getExecutor(), appResFactory, CacheMemorySource.class, sncpAddr, sameGroupTransport, diffGroupTransports); + final CacheMemorySource source = Sncp.createLocalService(resourceName, getExecutor(), appResFactory, CacheMemorySource.class, sncpAddr, Sncp.getSncpGroup(srcService), Sncp.getGroups(srcService), Sncp.getConf(srcService), sameGroupTransport, diffGroupTransports); Type genericType = field.getGenericType(); ParameterizedType pt = (genericType instanceof ParameterizedType) ? (ParameterizedType) genericType : null; Type valType = pt == null ? null : pt.getActualTypeArguments()[1]; @@ -273,9 +276,8 @@ public abstract class NodeServer { if ((src instanceof WebSocketNodeService) && sncpAddr != null) { //只有WebSocketNodeService的服务才需要给SNCP服务注入CacheMemorySource NodeSncpServer sncpServer = application.findNodeSncpServer(sncpAddr); Set gs = application.findSncpGroups(sameGroupTransport, diffGroupTransports); - ServiceWrapper wrapper = new ServiceWrapper(CacheMemorySource.class, (Service) source, resourceName, sncpServer.getSncpGroup(), gs, null); - sncpServer.getSncpServer().addSncpServlet(wrapper); - logger.info("[" + Thread.currentThread().getName() + "] Load Service " + wrapper.getService()); + sncpServer.getSncpServer().addSncpServlet((Service) source); + logger.info("[" + Thread.currentThread().getName() + "] Load Service " + source); } logger.info("[" + Thread.currentThread().getName() + "] Load Source " + source); } catch (Exception e) { @@ -305,7 +307,7 @@ public abstract class NodeServer { if (entry.getName().contains("$")) throw new RuntimeException(" value cannot contains '$' in " + entry.getProperty()); Service oldother = resourceFactory.find(entry.getName(), serviceImplClass); if (oldother != null) { //Server加载Service时需要判断是否已经加载过了。 - interceptorServiceWrappers.add(new NodeInterceptor.InterceptorServiceWrapper(entry.getName(), serviceImplClass, oldother)); + interceptorServices.add(oldother); continue; } final HashSet groups = entry.getGroups(); //groups.isEmpty()表示没有配置groups属性。 @@ -321,26 +323,26 @@ public abstract class NodeServer { Service service; if (localed) { //本地模式 service = Sncp.createLocalService(entry.getName(), getExecutor(), application.getResourceFactory(), serviceImplClass, - NodeServer.this.sncpAddress, loadTransport(NodeServer.this.sncpGroup), loadTransports(groups)); + NodeServer.this.sncpAddress, NodeServer.this.sncpGroup, groups, entry.getProperty(), loadTransport(NodeServer.this.sncpGroup), loadTransports(groups)); } else { - service = Sncp.createRemoteService(entry.getName(), getExecutor(), serviceImplClass, NodeServer.this.sncpAddress, loadTransport(groups)); + service = Sncp.createRemoteService(entry.getName(), getExecutor(), serviceImplClass, NodeServer.this.sncpAddress, null, groups, entry.getProperty(), loadTransport(groups)); } if (SncpClient.parseMethod(serviceImplClass).isEmpty()) return; //class没有可用的方法, 通常为BaseService - final ServiceWrapper wrapper = new ServiceWrapper(serviceImplClass, service, entry.getName(), localed ? NodeServer.this.sncpGroup : null, groups, entry.getProperty()); - for (final Class restype : wrapper.getTypes()) { - if (resourceFactory.find(wrapper.getName(), restype) == null) { - regFactory.register(wrapper.getName(), restype, wrapper.getService()); - if (needinject) rf.inject(wrapper.getService()); //动态加载的Service也存在按需加载的注入资源 + //final ServiceWrapper wrapper = new ServiceWrapper(serviceImplClass, service, entry.getName(), localed ? NodeServer.this.sncpGroup : null, groups, entry.getProperty()); + for (final Class restype : Sncp.getResourceTypes(service)) { + if (resourceFactory.find(entry.getName(), restype) == null) { + regFactory.register(entry.getName(), restype, service); + if (needinject) rf.inject(service); //动态加载的Service也存在按需加载的注入资源 } else if (isSNCP() && !entry.isAutoload()) { - throw new RuntimeException(ServiceWrapper.class.getSimpleName() + "(class:" + serviceImplClass.getName() + ", name:" + entry.getName() + ", group:" + groups + ") is repeat."); + throw new RuntimeException(restype.getSimpleName() + "(class:" + serviceImplClass.getName() + ", name:" + entry.getName() + ", group:" + groups + ") is repeat."); } } - if (wrapper.isRemote()) { - remoteServiceWrappers.add(wrapper); + if (Sncp.isRemote(service)) { + remoteServices.add(service); } else { - localServiceWrappers.add(wrapper); - interceptorServiceWrappers.add(new NodeInterceptor.InterceptorServiceWrapper(entry.getName(), serviceImplClass, service)); - if (consumer != null) consumer.accept(wrapper); + localServices.add(service); + interceptorServices.add(service); + if (consumer != null) consumer.accept(service); } } catch (RuntimeException ex) { throw ex; @@ -352,7 +354,9 @@ public abstract class NodeServer { ResourceFactory.ResourceLoader resourceLoader = (ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) -> { runner.accept(rf, true); }; - for (final Class restype : ServiceWrapper.parseTypes(entry.getType())) { + ResourceType rty = entry.getType().getAnnotation(ResourceType.class); + Class[] resTypes = rty == null ? new Class[]{} : rty.value(); + for (final Class restype : resTypes) { resourceFactory.register(resourceLoader, restype); } } else { @@ -366,30 +370,38 @@ public abstract class NodeServer { final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null; //---------------- inject ---------------- - new ArrayList<>(localServiceWrappers).forEach(y -> { - resourceFactory.inject(y.getService(), NodeServer.this); + new ArrayList<>(localServices).forEach(y -> { + resourceFactory.inject(y, NodeServer.this); + calcMaxLength(y); }); - new ArrayList<>(remoteServiceWrappers).forEach(y -> { - resourceFactory.inject(y.getService(), NodeServer.this); + new ArrayList<>(remoteServices).forEach(y -> { + resourceFactory.inject(y, NodeServer.this); + calcMaxLength(y); }); + if (sb != null) { - remoteServiceWrappers.forEach(y -> { - sb.append(threadName).append(y.toSimpleString()).append(" load and inject").append(LINE_SEPARATOR); + remoteServices.forEach(y -> { + sb.append(threadName).append(Sncp.toSimpleString(y, maxNameLength, maxClassNameLength)).append(" load and inject").append(LINE_SEPARATOR); }); } //----------------- init ----------------- - List swlist = new ArrayList<>(localServiceWrappers); - Collections.sort(swlist); - localServiceWrappers.clear(); - localServiceWrappers.addAll(swlist); + List swlist = new ArrayList<>(localServices); + Collections.sort(swlist, (o1, o2) -> { + int rs = Sncp.getResourceTypes(o1)[0].getName().compareTo(Sncp.getResourceTypes(o2)[0].getName()); + if (rs == 0) rs = Sncp.getResourceName(o1).compareTo(Sncp.getResourceName(o2)); + return rs; + }); + localServices.clear(); + localServices.addAll(swlist); final List slist = sb == null ? null : new CopyOnWriteArrayList<>(); - CountDownLatch clds = new CountDownLatch(localServiceWrappers.size()); - localServiceWrappers.parallelStream().forEach(y -> { + CountDownLatch clds = new CountDownLatch(localServices.size()); + localServices.parallelStream().forEach(y -> { try { long s = System.currentTimeMillis(); - y.getService().init(y.getConf()); + y.init(Sncp.getConf(y)); long e = System.currentTimeMillis() - s; - if (slist != null) slist.add(new StringBuilder().append(threadName).append(y.toSimpleString()).append(" load and init in ").append(e).append(" ms").append(LINE_SEPARATOR).toString()); + String serstr = Sncp.toSimpleString(y, maxNameLength, maxClassNameLength); + if (slist != null) slist.add(new StringBuilder().append(threadName).append(serstr).append(" load and init in ").append(e).append(" ms").append(LINE_SEPARATOR).toString()); } finally { clds.countDown(); } @@ -405,6 +417,20 @@ public abstract class NodeServer { if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString()); } + private void calcMaxLength(Service y) { //计算toString中的长度 + maxNameLength = Math.max(maxNameLength, Sncp.getResourceName(y).length()); + StringBuilder s = new StringBuilder(); + Class[] types = Sncp.getResourceTypes(y); + if (types.length == 1) { + s.append(types[0].getName()); + } else { + s.append('['); + s.append(Arrays.asList(types).stream().map((Class t) -> t.getName()).collect(Collectors.joining(","))); + s.append(']'); + } + maxClassNameLength = Math.max(maxClassNameLength, s.length() + 1); + } + protected List loadTransports(final HashSet groups) { if (groups == null) return null; final List transports = new ArrayList<>(); @@ -559,12 +585,12 @@ public abstract class NodeServer { public void shutdown() throws IOException { if (interceptor != null) interceptor.preShutdown(this); final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null; - localServiceWrappers.forEach(y -> { + localServices.forEach(y -> { long s = System.currentTimeMillis(); - y.getService().destroy(y.getConf()); + y.destroy(Sncp.getConf(y)); long e = System.currentTimeMillis() - s; if (e > 2 && sb != null) { - sb.append(y.toSimpleString()).append(" destroy ").append(e).append("ms").append(LINE_SEPARATOR); + sb.append(Sncp.toSimpleString(y, maxNameLength, maxClassNameLength)).append(" destroy ").append(e).append("ms").append(LINE_SEPARATOR); } }); if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString()); @@ -575,16 +601,16 @@ public abstract class NodeServer { return (T) server; } - public Set getInterceptorServiceWrappers() { - return new LinkedHashSet<>(interceptorServiceWrappers); + public Set getInterceptorServices() { + return new LinkedHashSet<>(interceptorServices); } - public Set getLocalServiceWrappers() { - return new LinkedHashSet<>(localServiceWrappers); + public Set getLocalServices() { + return new LinkedHashSet<>(localServices); } - public Set getRemoteServiceWrappers() { - return new LinkedHashSet<>(remoteServiceWrappers); + public Set getRemoteServices() { + return new LinkedHashSet<>(remoteServices); } } diff --git a/src/org/redkale/boot/NodeSncpServer.java b/src/org/redkale/boot/NodeSncpServer.java index ef4e9a99a..c423418db 100644 --- a/src/org/redkale/boot/NodeSncpServer.java +++ b/src/org/redkale/boot/NodeSncpServer.java @@ -10,6 +10,7 @@ import java.util.*; import java.util.logging.*; import org.redkale.net.*; import org.redkale.net.sncp.*; +import org.redkale.service.Service; import org.redkale.util.*; /** @@ -48,8 +49,8 @@ public class NodeSncpServer extends NodeServer { return sncpServer == null ? null : sncpServer.getSocketAddress(); } - public void consumerAccept(ServiceWrapper wrapper) { - if (this.consumer != null) this.consumer.accept(wrapper); + public void consumerAccept(Service service) { + if (this.consumer != null) this.consumer.accept(service); } @Override diff --git a/src/org/redkale/net/sncp/ServiceWrapper.java b/src/org/redkale/net/sncp/ServiceWrapper.java deleted file mode 100644 index d782d5bd8..000000000 --- a/src/org/redkale/net/sncp/ServiceWrapper.java +++ /dev/null @@ -1,156 +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.net.sncp; - -import java.util.*; -import java.util.stream.Collectors; -import org.redkale.service.Service; -import org.redkale.util.*; - -/** - * Service对象的封装类 - * - * - * 详情见: https://redkale.org - * - * @author zhangjx - * @param Service的子类 - */ -public final class ServiceWrapper implements Comparable { - - private static volatile int maxClassNameLength = 0; - - private static volatile int maxNameLength = 0; - - private final T service; - - private final AnyValue conf; - - private final String sncpGroup; //自身的组节点名 可能为null - - private final Set groups; //所有的组节点,包含自身 - - private final String name; - - private final boolean remote; - - private final Class[] types; - - public ServiceWrapper(T service, String name, String sncpGroup, Set groups, AnyValue conf) { - this(null, service, name, sncpGroup, groups, conf); - } - - @SuppressWarnings("unchecked") - public ServiceWrapper(Class type, T service, String name, String sncpGroup, Set groups, AnyValue conf) { - this.service = service; - this.conf = conf; - this.sncpGroup = sncpGroup; - this.groups = groups; - this.name = name; - this.remote = Sncp.isRemote(service); - ResourceType rty = service.getClass().getAnnotation(ResourceType.class); - this.types = rty == null ? new Class[]{type == null ? (Class) service.getClass() : type} : rty.value(); - - maxNameLength = Math.max(maxNameLength, name.length()); - StringBuilder s = new StringBuilder(); - if (this.types.length == 1) { - s.append(types[0].getName()); - } else { - s.append('['); - s.append(Arrays.asList(this.types).stream().map((Class t) -> t.getName()).collect(Collectors.joining(","))); - s.append(']'); - } - maxClassNameLength = Math.max(maxClassNameLength, s.length() + 1); - } - - public static Class[] parseTypes(final Class servicetype) { - ResourceType rty = servicetype.getAnnotation(ResourceType.class); - return rty == null ? new Class[]{servicetype} : rty.value(); - } - - @Override - public String toString() { - return toSimpleString(); - } - - public String toSimpleString() { - StringBuilder sb = new StringBuilder(); - sb.append(remote ? "RemoteService" : "LocalService "); - int len; - if (types.length == 1) { - sb.append("(type= ").append(types[0].getName()); - len = maxClassNameLength - types[0].getName().length(); - } else { - StringBuilder s = new StringBuilder(); - s.append('['); - s.append(Arrays.asList(this.types).stream().map((Class t) -> t.getName()).collect(Collectors.joining(","))); - s.append(']'); - sb.append("(types=").append(s); - len = maxClassNameLength - s.length(); - } - - for (int i = 0; i < len; i++) { - sb.append(' '); - } - sb.append(", name='").append(name).append("'"); - for (int i = 0; i < maxNameLength - name.length(); i++) { - sb.append(' '); - } - sb.append(")"); - return sb.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null) return false; - if (!(obj instanceof ServiceWrapper)) return false; - ServiceWrapper other = (ServiceWrapper) obj; - return (this.types[0].equals(other.types[0]) && this.remote == other.remote && this.name.equals(other.name) && Objects.equals(this.sncpGroup, other.sncpGroup)); - } - - @Override - public int hashCode() { - int hash = 3; - hash = 67 * hash + Objects.hashCode(this.types[0]); - hash = 67 * hash + Objects.hashCode(this.sncpGroup); - hash = 67 * hash + Objects.hashCode(this.name); - hash = 67 * hash + (this.remote ? 1 : 0); - return hash; - } - - @Override - public int compareTo(ServiceWrapper o) { - int rs = this.types[0].getName().compareTo(o.types[0].getName()); - if (rs == 0) rs = this.name.compareTo(o.name); - return rs; - } - - public Class[] getTypes() { - return types; - } - - public Service getService() { - return service; - } - - public AnyValue getConf() { - return conf; - } - - public String getName() { - return name; - } - - public boolean isRemote() { - return remote; - } - - public Set getGroups() { - return groups; - } - -} diff --git a/src/org/redkale/net/sncp/Sncp.java b/src/org/redkale/net/sncp/Sncp.java index e8fe34e16..bcd20be04 100644 --- a/src/org/redkale/net/sncp/Sncp.java +++ b/src/org/redkale/net/sncp/Sncp.java @@ -11,6 +11,7 @@ import java.net.InetSocketAddress; import java.security.*; import java.util.*; import java.util.function.Consumer; +import java.util.stream.Collectors; import javax.annotation.Resource; import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES; import jdk.internal.org.objectweb.asm.*; @@ -92,6 +93,62 @@ public abstract class Sncp { return dyn != null && dyn.remote(); } + public static String getResourceName(Service service) { + if (service == null) return null; + Resource res = service.getClass().getAnnotation(Resource.class); + return res == null ? null : res.name(); + } + + public static Class getServiceType(Service service) { + if (service == null) return null; + try { + Field ts = service.getClass().getDeclaredField(FIELDPREFIX + "_service_type"); + ts.setAccessible(true); + return (Class) ts.get(service); + } catch (Exception e) { + throw new RuntimeException(service + " not found " + FIELDPREFIX + "_service_type"); + } + } + + public static Class[] getResourceTypes(Service service) { + if (service == null) return null; + ResourceType types = service.getClass().getAnnotation(ResourceType.class); + return types == null ? new Class[]{getServiceType(service)} : types.value(); + } + + public static String getSncpGroup(Service service) { + if (service == null) return null; + try { + Field ts = service.getClass().getDeclaredField(FIELDPREFIX + "_sncpGroup"); + ts.setAccessible(true); + return (String) ts.get(service); + } catch (Exception e) { + throw new RuntimeException(service + " not found " + FIELDPREFIX + "_sncpGroup"); + } + } + + public static Set getGroups(Service service) { + if (service == null) return null; + try { + Field ts = service.getClass().getDeclaredField(FIELDPREFIX + "_groups"); + ts.setAccessible(true); + return (Set) ts.get(service); + } catch (Exception e) { + throw new RuntimeException(service + " not found " + FIELDPREFIX + "_groups"); + } + } + + public static AnyValue getConf(Service service) { + if (service == null) return null; + try { + Field ts = service.getClass().getDeclaredField(FIELDPREFIX + "_conf"); + ts.setAccessible(true); + return (AnyValue) ts.get(service); + } catch (Exception e) { + throw new RuntimeException(service + " not found " + FIELDPREFIX + "_conf"); + } + } + public static SncpClient getSncpClient(Service service) { if (service == null) return null; try { @@ -155,10 +212,43 @@ public abstract class Sncp { throw new RuntimeException(param + "'s sncp_getParams method cannot final modifier"); } else if (m.getName().equals("sncp_setParams") && Modifier.isFinal(m.getModifiers())) { throw new RuntimeException(param + "'s sncp_setParams method cannot final modifier"); + } else if (m.getName().equals("sncp_setFuture") && Modifier.isFinal(m.getModifiers())) { + throw new RuntimeException(param + "'s sncp_setFuture method cannot final modifier"); + } else if (m.getName().equals("sncp_getFuture") && Modifier.isFinal(m.getModifiers())) { + throw new RuntimeException(param + "'s sncp_getFuture method cannot final modifier"); } } } + public static String toSimpleString(final Service service, int maxNameLength, int maxClassNameLength) { + StringBuilder sb = new StringBuilder(); + sb.append(isRemote(service) ? "RemoteService" : "LocalService "); + int len; + Class[] types = getResourceTypes(service); + String name = getResourceName(service); + if (types.length == 1) { + sb.append("(type= ").append(types[0].getName()); + len = maxClassNameLength - types[0].getName().length(); + } else { + StringBuilder s = new StringBuilder(); + s.append('['); + s.append(Arrays.asList(types).stream().map((Class t) -> t.getName()).collect(Collectors.joining(","))); + s.append(']'); + sb.append("(types=").append(s); + len = maxClassNameLength - s.length(); + } + + for (int i = 0; i < len; i++) { + sb.append(' '); + } + sb.append(", name='").append(name).append("'"); + for (int i = 0; i < maxNameLength - name.length(); i++) { + sb.append(' '); + } + sb.append(")"); + return sb.toString(); + } + /** *
      * public class TestService implements Service{
@@ -185,12 +275,20 @@ public abstract class Sncp {
      * @ResourceType({TestService.class})
      * public final class _DynLocalTestService extends TestService{
      *
+     *      private static final Class _redkale_service_type = TestService.class;
+     *
      *      @Resource
      *      private BsonConvert _redkale_bsonConvert;
      *
      *      @Resource
      *      private JsonConvert _redkale_jsonConvert;
      *
+     *      private AnyValue _redkale_conf;
+     *
+     *      private String _redkale_sncpGroup; //自身的组节点名 可能为null
+     *
+     *      private Set<String> groups; //所有的组节点,包含自身
+     *
      *      private Transport _redkale_sameGroupTransport;
      *
      *      private Transport[] _redkale_diffGroupTransports;
@@ -235,36 +333,38 @@ public abstract class Sncp {
      *
      * 创建Service的本地模式Class
      *
-     * @param           Service子类
-     * @param name         资源名
-     * @param serviceClass Service类
+     * @param               Service子类
+     * @param name             资源名
+     * @param serviceImplClass Service类
      *
      * @return Service实例
      */
     @SuppressWarnings("unchecked")
-    protected static  Class createLocalServiceClass(final String name, final Class serviceClass) {
-        if (serviceClass == null) return null;
-        if (!Service.class.isAssignableFrom(serviceClass)) return serviceClass;
-        int mod = serviceClass.getModifiers();
-        if (!java.lang.reflect.Modifier.isPublic(mod)) return serviceClass;
-        if (java.lang.reflect.Modifier.isAbstract(mod)) return serviceClass;
-        final List methods = SncpClient.parseMethod(serviceClass);
-        final String supDynName = serviceClass.getName().replace('.', '/');
+    protected static  Class createLocalServiceClass(final String name, final Class serviceImplClass) {
+        if (serviceImplClass == null) return null;
+        if (!Service.class.isAssignableFrom(serviceImplClass)) return serviceImplClass;
+        int mod = serviceImplClass.getModifiers();
+        if (!java.lang.reflect.Modifier.isPublic(mod)) return serviceImplClass;
+        if (java.lang.reflect.Modifier.isAbstract(mod)) return serviceImplClass;
+        final List methods = SncpClient.parseMethod(serviceImplClass);
+        final String supDynName = serviceImplClass.getName().replace('.', '/');
         final String clientName = SncpClient.class.getName().replace('.', '/');
         final String clientDesc = Type.getDescriptor(SncpClient.class);
         final String bsonConvertDesc = Type.getDescriptor(BsonConvert.class);
         final String jsonConvertDesc = Type.getDescriptor(JsonConvert.class);
+        final String stringDesc = Type.getDescriptor(String.class);
+        final String anyValueDesc = Type.getDescriptor(AnyValue.class);
         final String sncpDynDesc = Type.getDescriptor(SncpDyn.class);
         final String transportDesc = Type.getDescriptor(Transport.class);
         final String transportsDesc = Type.getDescriptor(Transport[].class);
         ClassLoader loader = Sncp.class.getClassLoader();
-        String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + LOCALPREFIX + serviceClass.getSimpleName();
+        String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + LOCALPREFIX + serviceImplClass.getSimpleName();
         if (!name.isEmpty()) {
             boolean normal = true;
             for (char ch : name.toCharArray()) {
                 if (!((ch >= '0' && ch <= '9') || ch == '_' || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))) normal = false;
             }
-            if (!normal) throw new RuntimeException(serviceClass + "'s resource name is illegal, must be 0-9 _ a-z A-Z");
+            if (!normal) throw new RuntimeException(serviceImplClass + "'s resource name is illegal, must be 0-9 _ a-z A-Z");
             newDynName += "_" + (normal ? name : hash(name));
         }
         try {
@@ -289,7 +389,7 @@ public abstract class Sncp {
             av0.visitEnd();
         }
         { //给新类加上 原有的Annotation
-            for (Annotation ann : serviceClass.getAnnotations()) {
+            for (Annotation ann : serviceImplClass.getAnnotations()) {
                 if (ann instanceof Resource || ann instanceof SncpDyn || ann instanceof ResourceType) continue;
                 visitAnnotation(cw.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
             }
@@ -298,9 +398,9 @@ public abstract class Sncp {
             av0 = cw.visitAnnotation(Type.getDescriptor(ResourceType.class), true);
             {
                 AnnotationVisitor av1 = av0.visitArray("value");
-                ResourceType rty = serviceClass.getAnnotation(ResourceType.class);
+                ResourceType rty = serviceImplClass.getAnnotation(ResourceType.class);
                 if (rty == null) {
-                    av1.visit(null, Type.getType(Type.getDescriptor(serviceClass)));
+                    av1.visit(null, Type.getType(Type.getDescriptor(serviceImplClass)));
                 } else {
                     for (Class cl : rty.value()) {
                         av1.visit(null, Type.getType(Type.getDescriptor(cl)));
@@ -310,7 +410,10 @@ public abstract class Sncp {
             }
             av0.visitEnd();
         }
-
+        {
+            fv = cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, FIELDPREFIX + "_service_type", "Ljava/lang/Class;", null, null);
+            fv.visitEnd();
+        }
         {
             fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_bsonConvert", bsonConvertDesc, null, null);
             av0 = fv.visitAnnotation("Ljavax/annotation/Resource;", true);
@@ -323,6 +426,18 @@ public abstract class Sncp {
             av0.visitEnd();
             fv.visitEnd();
         }
+        {
+            fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_conf", anyValueDesc, null, null);
+            fv.visitEnd();
+        }
+        {
+            fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_sncpGroup", stringDesc, null, null);
+            fv.visitEnd();
+        }
+        {
+            fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_groups", "Ljava/util/Set;", "Ljava/util/Set;", null);
+            fv.visitEnd();
+        }
         {
             fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_sameGroupTransport", transportDesc, null, null);
             fv.visitEnd();
@@ -340,6 +455,14 @@ public abstract class Sncp {
             fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_selfstring", "Ljava/lang/String;", null, null);
             fv.visitEnd();
         }
+        {//静态构造函数
+            mv = new AsmMethodVisitor(cw.visitMethod(ACC_STATIC, "", "()V", null, null));
+            mv.visitLdcInsn(Type.getType(Type.getDescriptor(serviceImplClass)));
+            mv.visitFieldInsn(PUTSTATIC, newDynName, FIELDPREFIX + "_service_type", "Ljava/lang/Class;");
+            mv.visitInsn(RETURN);
+            mv.visitMaxs(1, 0);
+            mv.visitEnd();
+        }
         { //构造函数
             mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "", "()V", null, null));
             //mv.setDebug(true);
@@ -762,6 +885,10 @@ public abstract class Sncp {
         }
     }
 
+    public static  T createSimpleLocalService(final String name, final Class serviceImplClass, final InetSocketAddress clientAddress, final Transport sameGroupTransport) {
+        return createLocalService(name, null, ResourceFactory.root(), serviceImplClass, clientAddress, null, new HashSet<>(), null, sameGroupTransport, null);
+    }
+
     /**
      *
      * 创建本地模式Service实例
@@ -770,16 +897,28 @@ public abstract class Sncp {
      * @param name                资源名
      * @param executor            线程池
      * @param resourceFactory     资源容器
-     * @param serviceImplClass        Service类
+     * @param serviceImplClass    Service类
      * @param clientAddress       本地IP地址
+     * @param sncpGroup           自身的组节点名 可能为null
+     * @param groups              所有的组节点,包含自身
+     * @param conf                启动配置项
      * @param sameGroupTransport  同组的通信组件
      * @param diffGroupTransports 异组的通信组件列表
      *
      * @return Service的本地模式实例
      */
     @SuppressWarnings("unchecked")
-    public static  T createLocalService(final String name, final Consumer executor, final ResourceFactory resourceFactory,
-        final Class serviceImplClass, final InetSocketAddress clientAddress, final Transport sameGroupTransport, final Collection diffGroupTransports) {
+    public static  T createLocalService(
+        final String name,
+        final Consumer executor,
+        final ResourceFactory resourceFactory,
+        final Class serviceImplClass,
+        final InetSocketAddress clientAddress,
+        final String sncpGroup,
+        final Set groups,
+        final AnyValue conf,
+        final Transport sameGroupTransport,
+        final Collection diffGroupTransports) {
         try {
             final Class newClazz = createLocalServiceClass(name, serviceImplClass);
             T rs = (T) newClazz.newInstance();
@@ -813,7 +952,7 @@ public abstract class Sncp {
                             }
                         }
                         if (remoteService == null && remoteTransport != null) {
-                            remoteService = createRemoteService(name, executor, serviceImplClass, clientAddress, remoteTransport);
+                            remoteService = createRemoteService(name, executor, serviceImplClass, clientAddress, sncpGroup, groups, conf, remoteTransport);
                         }
                         if (remoteService != null) field.set(rs, remoteService);
                     }
@@ -836,13 +975,13 @@ public abstract class Sncp {
                     sb.append(", serviceid = ").append(client.getServiceid());
                     sb.append(", serviceversion = ").append(client.getServiceversion());
                     sb.append(", action.size = ").append(client.getActionCount());
-                    List groups = new ArrayList<>();
-                    if (sameGroupTransport != null) groups.add(sameGroupTransport.getName());
-                    if (diffGroupTransports != null) {
-                        for (Transport t : diffGroupTransports) {
-                            groups.add(t.getName());
-                        }
-                    }
+//                    List groups = new ArrayList<>();
+//                    if (sameGroupTransport != null) groups.add(sameGroupTransport.getName());
+//                    if (diffGroupTransports != null) {
+//                        for (Transport t : diffGroupTransports) {
+//                            groups.add(t.getName());
+//                        }
+//                    }
                     sb.append(", address = ").append(clientAddress).append(", groups = ").append(groups);
                     sb.append(", sameaddrs = ").append(sameGroupTransport == null ? null : Arrays.asList(sameGroupTransport.getRemoteAddresses()));
 
@@ -862,6 +1001,21 @@ public abstract class Sncp {
                 s.set(rs, sb.toString());
             }
             if (client == null) return rs;
+            {
+                Field c = newClazz.getDeclaredField(FIELDPREFIX + "_sncpGroup");
+                c.setAccessible(true);
+                c.set(rs, sncpGroup);
+            }
+            {
+                Field c = newClazz.getDeclaredField(FIELDPREFIX + "_groups");
+                c.setAccessible(true);
+                c.set(rs, groups);
+            }
+            {
+                Field c = newClazz.getDeclaredField(FIELDPREFIX + "_conf");
+                c.setAccessible(true);
+                c.set(rs, conf);
+            }
             {
                 Field c = newClazz.getDeclaredField(FIELDPREFIX + "_sameGroupTransport");
                 c.setAccessible(true);
@@ -881,6 +1035,10 @@ public abstract class Sncp {
 
     }
 
+    public static  T createSimpleRemoteService(final String name, final Class serviceTypeOrImplClass, final InetSocketAddress clientAddress, final Transport transport) {
+        return createRemoteService(name, null, serviceTypeOrImplClass, clientAddress, (String) null, new HashSet<>(), (AnyValue) null, transport);
+    }
+
     /**
      * 
      * @Resource(name = "")
@@ -888,12 +1046,20 @@ public abstract class Sncp {
      * @ResourceType({TestService.class})
      * public final class _DynRemoteTestService extends TestService{
      *
+     *      private static final Class _redkale_service_type = TestService.class;
+     *
      *      @Resource
      *      private BsonConvert _redkale_bsonConvert;
      *
      *      @Resource
      *      private JsonConvert _redkale_jsonConvert;
      *
+     *      private String _redkale_sncpGroup; //自身的组节点名 可能为null
+     *
+     *      private Set<String> groups; //所有的组节点,包含自身
+     *
+     *      private AnyValue _redkale_conf;
+     *
      *      private Transport _redkale_transport;
      *
      *      private SncpClient _redkale_client;
@@ -934,18 +1100,28 @@ public abstract class Sncp {
      *
      * 创建远程模式的Service实例
      *
-     * @param            Service泛型
-     * @param name          资源名
-     * @param executor      线程池
-     * @param serviceTypeOrImplClass  Service类
-     * @param clientAddress 本地IP地址
-     * @param transport     通信组件
+     * @param                     Service泛型
+     * @param name                   资源名
+     * @param executor               线程池
+     * @param serviceTypeOrImplClass Service类
+     * @param clientAddress          本地IP地址
+     * @param sncpGroup              自身的组节点名 可能为null
+     * @param groups                 所有的组节点,包含自身
+     * @param conf                   启动配置项
+     * @param transport              通信组件
      *
      * @return Service的远程模式实例
      */
     @SuppressWarnings("unchecked")
-    public static  T createRemoteService(final String name, final Consumer executor, final Class serviceTypeOrImplClass,
-        final InetSocketAddress clientAddress, final Transport transport) {
+    public static  T createRemoteService(
+        final String name,
+        final Consumer executor,
+        final Class serviceTypeOrImplClass,
+        final InetSocketAddress clientAddress,
+        final String sncpGroup,
+        final Set groups,
+        final AnyValue conf,
+        final Transport transport) {
         if (serviceTypeOrImplClass == null) return null;
         if (!Service.class.isAssignableFrom(serviceTypeOrImplClass)) return null;
         int mod = serviceTypeOrImplClass.getModifiers();
@@ -958,6 +1134,7 @@ public abstract class Sncp {
         final String bsonConvertDesc = Type.getDescriptor(BsonConvert.class);
         final String jsonConvertDesc = Type.getDescriptor(JsonConvert.class);
         final String transportDesc = Type.getDescriptor(Transport.class);
+        final String stringDesc = Type.getDescriptor(String.class);
         final String anyValueDesc = Type.getDescriptor(AnyValue.class);
         ClassLoader loader = Sncp.class.getClassLoader();
         String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + REMOTEPREFIX + serviceTypeOrImplClass.getSimpleName();
@@ -1026,6 +1203,10 @@ public abstract class Sncp {
                 visitAnnotation(cw.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
             }
         }
+        {
+            fv = cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, FIELDPREFIX + "_service_type", "Ljava/lang/Class;", null, null);
+            fv.visitEnd();
+        }
         {
             fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_bsonConvert", bsonConvertDesc, null, null);
             av0 = fv.visitAnnotation("Ljavax/annotation/Resource;", true);
@@ -1038,6 +1219,18 @@ public abstract class Sncp {
             av0.visitEnd();
             fv.visitEnd();
         }
+        {
+            fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_sncpGroup", stringDesc, null, null);
+            fv.visitEnd();
+        }
+        {
+            fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_groups", "Ljava/util/Set;", "Ljava/util/Set;", null);
+            fv.visitEnd();
+        }
+        {
+            fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_conf", anyValueDesc, null, null);
+            fv.visitEnd();
+        }
         {
             fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_transport", transportDesc, null, null);
             fv.visitEnd();
@@ -1050,6 +1243,14 @@ public abstract class Sncp {
             fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_selfstring", "Ljava/lang/String;", null, null);
             fv.visitEnd();
         }
+        {//静态构造函数
+            mv = new AsmMethodVisitor(cw.visitMethod(ACC_STATIC, "", "()V", null, null));
+            mv.visitLdcInsn(Type.getType(Type.getDescriptor(serviceTypeOrImplClass)));
+            mv.visitFieldInsn(PUTSTATIC, newDynName, FIELDPREFIX + "_service_type", "Ljava/lang/Class;");
+            mv.visitInsn(RETURN);
+            mv.visitMaxs(1, 0);
+            mv.visitEnd();
+        }
         { //构造函数
             mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "", "()V", null, null));
             //mv.setDebug(true);
@@ -1199,13 +1400,32 @@ public abstract class Sncp {
         }.loadClass(newDynName.replace('/', '.'), bytes);
         try {
             T rs = (T) newClazz.newInstance();
-            Field c = newClazz.getDeclaredField(FIELDPREFIX + "_client");
-            c.setAccessible(true);
             SncpClient client = new SncpClient(name, serviceTypeOrImplClass, rs, executor, true, realed ? createLocalServiceClass(name, serviceTypeOrImplClass) : serviceTypeOrImplClass, clientAddress);
-            c.set(rs, client);
-            Field t = newClazz.getDeclaredField(FIELDPREFIX + "_transport");
-            t.setAccessible(true);
-            t.set(rs, transport);
+            {
+                Field c = newClazz.getDeclaredField(FIELDPREFIX + "_client");
+                c.setAccessible(true);
+                c.set(rs, client);
+            }
+            {
+                Field c = newClazz.getDeclaredField(FIELDPREFIX + "_conf");
+                c.setAccessible(true);
+                c.set(rs, conf);
+            }
+            {
+                Field c = newClazz.getDeclaredField(FIELDPREFIX + "_sncpGroup");
+                c.setAccessible(true);
+                c.set(rs, sncpGroup);
+            }
+            {
+                Field c = newClazz.getDeclaredField(FIELDPREFIX + "_groups");
+                c.setAccessible(true);
+                c.set(rs, groups);
+            }
+            {
+                Field t = newClazz.getDeclaredField(FIELDPREFIX + "_transport");
+                t.setAccessible(true);
+                t.set(rs, transport);
+            }
             {
                 StringBuilder sb = new StringBuilder();
                 sb.append(newClazz.getName()).append("{name = '").append(name);
diff --git a/src/org/redkale/net/sncp/SncpClient.java b/src/org/redkale/net/sncp/SncpClient.java
index 7e6ec7b3c..86599e7c1 100644
--- a/src/org/redkale/net/sncp/SncpClient.java
+++ b/src/org/redkale/net/sncp/SncpClient.java
@@ -162,7 +162,7 @@ public final class SncpClient {
 
     protected final Consumer executor;
 
-    public  SncpClient(final String serviceName, final Class serviceType, final T service, final Consumer executor,
+    public  SncpClient(final String serviceName, final Class serviceTypeOrImplClass, final T service, final Consumer executor,
         final boolean remote, final Class serviceClass, final InetSocketAddress clientAddress) {
         this.remote = remote;
         this.executor = executor;
@@ -170,7 +170,10 @@ public final class SncpClient {
         this.serviceversion = 0;
         this.clientAddress = clientAddress;
         this.name = serviceName;
-        this.serviceid = Sncp.hash(serviceType.getName() + ':' + serviceName);
+        Class tn = serviceTypeOrImplClass;
+        ResourceType rt = (ResourceType) tn.getAnnotation(ResourceType.class);
+        if (rt != null && rt.value().length > 0) tn = rt.value()[0];
+        this.serviceid = Sncp.hash(tn.getName() + ':' + serviceName);
         final List methodens = new ArrayList<>();
         //------------------------------------------------------------------------------
         for (java.lang.reflect.Method method : parseMethod(serviceClass)) {
diff --git a/src/org/redkale/net/sncp/SncpServer.java b/src/org/redkale/net/sncp/SncpServer.java
index d21a0c84e..454a4fd5c 100644
--- a/src/org/redkale/net/sncp/SncpServer.java
+++ b/src/org/redkale/net/sncp/SncpServer.java
@@ -38,15 +38,15 @@ public final class SncpServer extends Server void addSncpServlet(Class serviceType, String name, T service, AnyValue conf) {
-        SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), name, serviceType, service);
+    public  void addSncpServlet(Class serviceTypeClass, String name, T service, AnyValue conf) {
+        SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), name, serviceTypeClass, service);
         this.prepare.addServlet(sds, null, conf);
     }
 
diff --git a/test/org/redkale/test/service/ABMainService.java b/test/org/redkale/test/service/ABMainService.java
index 9b88b0da9..ee684eaef 100644
--- a/test/org/redkale/test/service/ABMainService.java
+++ b/test/org/redkale/test/service/ABMainService.java
@@ -41,29 +41,29 @@ public class ABMainService implements Service {
         factory.register(JsonConvert.root());
         factory.register(BsonConvert.root());
         //------------------------ 初始化 CService ------------------------------------
-        CService cservice = Sncp.createLocalService("", null, ResourceFactory.root(), CService.class, new InetSocketAddress("127.0.0.1", 5577), null, null);
+        CService cservice = Sncp.createLocalService("", null, ResourceFactory.root(), CService.class, new InetSocketAddress("127.0.0.1", 5577), "", new HashSet<>(), (AnyValue) null, null, null);
         SncpServer cserver = new SncpServer();
         cserver.getLogger().setLevel(Level.WARNING);
-        cserver.addSncpServlet(new ServiceWrapper(cservice, "", "", new HashSet<>(), null));
+        cserver.addSncpServlet(cservice);
         cserver.init(DefaultAnyValue.create("port", 5577));
         cserver.start();
 
         //------------------------ 初始化 BCService ------------------------------------
         final Transport bctransport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, Utility.ofSet(new InetSocketAddress("127.0.0.1", 5577)));
-        BCService bcservice = Sncp.createLocalService("", null, ResourceFactory.root(), BCService.class, new InetSocketAddress("127.0.0.1", 5588), bctransport, null);
-        CService remoteCService = Sncp.createRemoteService("", null, CService.class, new InetSocketAddress("127.0.0.1", 5588), bctransport);
+        BCService bcservice = Sncp.createLocalService("", null, ResourceFactory.root(), BCService.class, new InetSocketAddress("127.0.0.1", 5588), "", new HashSet<>(), (AnyValue) null, bctransport, null);
+        CService remoteCService = Sncp.createRemoteService("", null, CService.class, new InetSocketAddress("127.0.0.1", 5588), "", new HashSet<>(), (AnyValue) null, bctransport);
         factory.inject(remoteCService);
         factory.register("", remoteCService);
         SncpServer bcserver = new SncpServer();
         bcserver.getLogger().setLevel(Level.WARNING);
-        bcserver.addSncpServlet(new ServiceWrapper(bcservice, "", "", new HashSet<>(), null));
+        bcserver.addSncpServlet(bcservice);
         bcserver.init(DefaultAnyValue.create("port", 5588));
         bcserver.start();
 
         //------------------------ 初始化 ABMainService ------------------------------------
         final Transport abtransport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, Utility.ofSet(new InetSocketAddress("127.0.0.1", 5588)));
-        ABMainService service = Sncp.createLocalService("", null, ResourceFactory.root(), ABMainService.class, new InetSocketAddress("127.0.0.1", 5599), bctransport, null);
-        BCService remoteBCService = Sncp.createRemoteService("", null, BCService.class, new InetSocketAddress("127.0.0.1", 5599), abtransport);
+        ABMainService service = Sncp.createLocalService("", null, ResourceFactory.root(), ABMainService.class, new InetSocketAddress("127.0.0.1", 5599), "", new HashSet<>(), (AnyValue) null, bctransport, null);
+        BCService remoteBCService = Sncp.createRemoteService("", null, BCService.class, new InetSocketAddress("127.0.0.1", 5599), "", new HashSet<>(), (AnyValue) null, abtransport);
         factory.inject(remoteBCService);
         factory.register("", remoteBCService);
 
diff --git a/test/org/redkale/test/service/TestService.java b/test/org/redkale/test/service/TestService.java
index 817db62fd..7e0be63b7 100644
--- a/test/org/redkale/test/service/TestService.java
+++ b/test/org/redkale/test/service/TestService.java
@@ -5,7 +5,6 @@
  */
 package org.redkale.test.service;
 
-import java.util.HashSet;
 import org.redkale.net.sncp.*;
 import org.redkale.service.Service;
 import org.redkale.util.*;
@@ -26,7 +25,7 @@ public class TestService implements Service {
     
     public static void main(String[] args) throws Throwable {
         SncpServer cserver = new SncpServer();
-        cserver.addSncpServlet(new ServiceWrapper(new TestService(), "", "", new HashSet<>(), null));
+        cserver.addSncpServlet(new TestService());
         cserver.init(AnyValue.DefaultAnyValue.create("port", 5577));
     }
 }
diff --git a/test/org/redkale/test/sncp/SncpTest.java b/test/org/redkale/test/sncp/SncpTest.java
index 931186e58..c9483b2e2 100644
--- a/test/org/redkale/test/sncp/SncpTest.java
+++ b/test/org/redkale/test/sncp/SncpTest.java
@@ -82,7 +82,7 @@ public class SncpTest {
         if (port2 > 0) set.add(new InetSocketAddress(myhost, port2));
         //String name, WatchFactory, ObjectPool, AsynchronousChannelGroup, InetSocketAddress clientAddress, Collection
         final Transport transport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, set);
-        final SncpTestIService service = Sncp.createRemoteService(serviceName, null, SncpTestIService.class, null, transport);
+        final SncpTestIService service = Sncp.createSimpleRemoteService(serviceName, SncpTestIService.class, addr, transport);
         ResourceFactory.root().inject(service);
 
 //        SncpTestBean bean = new SncpTestBean();
@@ -159,9 +159,9 @@ public class SncpTest {
                     if (port2 > 0) set.add(new InetSocketAddress(myhost, port2));
                     //String name, WatchFactory, ObjectPool, AsynchronousChannelGroup, InetSocketAddress clientAddress, Collection
                     final Transport transport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, set);
-                    SncpTestIService service = Sncp.createLocalService("", null, ResourceFactory.root(), SncpTestServiceImpl.class, addr, transport, null);
+                    SncpTestIService service = Sncp.createSimpleLocalService("", SncpTestServiceImpl.class, addr, transport);
                     ResourceFactory.root().inject(service);
-                    server.addSncpServlet(new ServiceWrapper(service, "", "", new HashSet<>(), null));
+                    server.addSncpServlet(service);
                     System.out.println(service);
                     AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue();
                     conf.addValue("host", "0.0.0.0");
@@ -193,8 +193,8 @@ public class SncpTest {
                     set.add(new InetSocketAddress(myhost, port));
                     //String name, WatchFactory, ObjectPool, AsynchronousChannelGroup, InetSocketAddress clientAddress, Collection
                     final Transport transport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, set);
-                    Service service = Sncp.createLocalService("", null, ResourceFactory.root(), SncpTestServiceImpl.class, addr, transport, null);
-                    server.addSncpServlet(new ServiceWrapper(service, "", "", new HashSet<>(), null));
+                    Service service = Sncp.createSimpleLocalService("", SncpTestServiceImpl.class, addr, transport);
+                    server.addSncpServlet(service);
                     AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue();
                     conf.addValue("host", "0.0.0.0");
                     conf.addValue("port", "" + port2);
diff --git a/test/org/redkale/test/sncp/SncpTestServiceImpl.java b/test/org/redkale/test/sncp/SncpTestServiceImpl.java
index eddfa6d14..0b6f294ed 100644
--- a/test/org/redkale/test/sncp/SncpTestServiceImpl.java
+++ b/test/org/redkale/test/sncp/SncpTestServiceImpl.java
@@ -7,6 +7,7 @@ package org.redkale.test.sncp;
 
 import java.lang.reflect.Method;
 import java.net.InetSocketAddress;
+import java.util.HashSet;
 import java.util.concurrent.CompletableFuture;
 import org.redkale.net.sncp.*;
 import org.redkale.service.*;
@@ -97,7 +98,7 @@ public class SncpTestServiceImpl implements SncpTestIService {
     }
 
     public static void main(String[] args) throws Exception {
-        Service service = Sncp.createLocalService("", null, ResourceFactory.root(), SncpTestServiceImpl.class, new InetSocketAddress("127.0.0.1", 7070), null, null);
+        Service service = Sncp.createLocalService("", null, ResourceFactory.root(), SncpTestServiceImpl.class, new InetSocketAddress("127.0.0.1", 7070), "", new HashSet<>(), (AnyValue) null, null, null);
         for (Method method : service.getClass().getDeclaredMethods()) {
             System.out.println(method);
         }
@@ -106,7 +107,7 @@ public class SncpTestServiceImpl implements SncpTestIService {
             System.out.println(method);
         }
         System.out.println("-----------------------------------");
-        service = Sncp.createRemoteService("", null, SncpTestServiceImpl.class, new InetSocketAddress("127.0.0.1", 7070), null);
+        service = Sncp.createSimpleRemoteService("",  SncpTestServiceImpl.class, new InetSocketAddress("127.0.0.1", 7070), null);
         for (Method method : service.getClass().getDeclaredMethods()) {
             System.out.println(method);
         }
@@ -115,7 +116,7 @@ public class SncpTestServiceImpl implements SncpTestIService {
             System.out.println(method);
         }
         System.out.println("-----------------------------------");
-        service = Sncp.createRemoteService("", null, SncpTestIService.class, new InetSocketAddress("127.0.0.1", 7070), null);
+        service = Sncp.createSimpleRemoteService("",  SncpTestIService.class, new InetSocketAddress("127.0.0.1", 7070), null);
         for (Method method : service.getClass().getDeclaredMethods()) {
             System.out.println(method);
         }