去掉ServiceWrapper
This commit is contained in:
@@ -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<Transport>) null);
|
||||
nodeService = Sncp.createLocalService(resourceName, getExecutor(), application.getResourceFactory(), WebSocketNodeService.class, (InetSocketAddress) null, (String) null, (Set<String>) null, (AnyValue) null, (Transport) null, (Collection<Transport>) 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<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey()));
|
||||
int max = 0;
|
||||
for (AbstractMap.SimpleEntry<String, String[]> 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<AbstractMap.SimpleEntry<String, String[]>> 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<String, String[]> as : ss) {
|
||||
if (as.getKey().length() > max) max = as.getKey().length();
|
||||
}
|
||||
sb.append(threadName).append(" ").append(LINE_SEPARATOR);
|
||||
for (AbstractMap.SimpleEntry<String, String[]> 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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T extends Service> {
|
||||
|
||||
private String name;
|
||||
|
||||
private Class<T> type;
|
||||
|
||||
private T service;
|
||||
|
||||
public InterceptorServiceWrapper() {
|
||||
}
|
||||
|
||||
public InterceptorServiceWrapper(String name, Class<T> 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<T> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(Class<T> 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public abstract class NodeServer {
|
||||
private InetSocketAddress sncpAddress;
|
||||
|
||||
//加载Service时的处理函数
|
||||
protected Consumer<ServiceWrapper> consumer;
|
||||
protected Consumer<Service> consumer;
|
||||
|
||||
//server节点的配置
|
||||
protected AnyValue serverConf;
|
||||
@@ -78,13 +78,17 @@ public abstract class NodeServer {
|
||||
protected NodeInterceptor interceptor;
|
||||
|
||||
//供interceptor使用的Service对象集合
|
||||
protected final Set<NodeInterceptor.InterceptorServiceWrapper> interceptorServiceWrappers = new LinkedHashSet<>();
|
||||
protected final Set<Service> interceptorServices = new LinkedHashSet<>();
|
||||
|
||||
//本地模式的Service对象集合
|
||||
protected final Set<ServiceWrapper> localServiceWrappers = new LinkedHashSet<>();
|
||||
protected final Set<Service> localServices = new LinkedHashSet<>();
|
||||
|
||||
//远程模式的Service对象集合
|
||||
protected final Set<ServiceWrapper> remoteServiceWrappers = new LinkedHashSet<>();
|
||||
protected final Set<Service> 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<Transport> 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<String> 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<Transport> 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<String> 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("<name> 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<String> groups = entry.getGroups(); //groups.isEmpty()表示<services>没有配置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<ServiceWrapper> swlist = new ArrayList<>(localServiceWrappers);
|
||||
Collections.sort(swlist);
|
||||
localServiceWrappers.clear();
|
||||
localServiceWrappers.addAll(swlist);
|
||||
List<Service> 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<String> 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<Transport> loadTransports(final HashSet<String> groups) {
|
||||
if (groups == null) return null;
|
||||
final List<Transport> 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<NodeInterceptor.InterceptorServiceWrapper> getInterceptorServiceWrappers() {
|
||||
return new LinkedHashSet<>(interceptorServiceWrappers);
|
||||
public Set<Service> getInterceptorServices() {
|
||||
return new LinkedHashSet<>(interceptorServices);
|
||||
}
|
||||
|
||||
public Set<ServiceWrapper> getLocalServiceWrappers() {
|
||||
return new LinkedHashSet<>(localServiceWrappers);
|
||||
public Set<Service> getLocalServices() {
|
||||
return new LinkedHashSet<>(localServices);
|
||||
}
|
||||
|
||||
public Set<ServiceWrapper> getRemoteServiceWrappers() {
|
||||
return new LinkedHashSet<>(remoteServiceWrappers);
|
||||
public Set<Service> getRemoteServices() {
|
||||
return new LinkedHashSet<>(remoteServices);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <T> Service的子类
|
||||
*/
|
||||
public final class ServiceWrapper<T extends Service> implements Comparable<ServiceWrapper> {
|
||||
|
||||
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<String> groups; //所有的组节点,包含自身
|
||||
|
||||
private final String name;
|
||||
|
||||
private final boolean remote;
|
||||
|
||||
private final Class[] types;
|
||||
|
||||
public ServiceWrapper(T service, String name, String sncpGroup, Set<String> groups, AnyValue conf) {
|
||||
this(null, service, name, sncpGroup, groups, conf);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ServiceWrapper(Class<T> type, T service, String name, String sncpGroup, Set<String> 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<T>) 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<? extends Service> 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<String> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<String> 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* <blockquote><pre>
|
||||
* 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 <T> Service子类
|
||||
* @param name 资源名
|
||||
* @param serviceClass Service类
|
||||
* @param <T> Service子类
|
||||
* @param name 资源名
|
||||
* @param serviceImplClass Service类
|
||||
*
|
||||
* @return Service实例
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static <T extends Service> Class<? extends T> createLocalServiceClass(final String name, final Class<T> 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<Method> methods = SncpClient.parseMethod(serviceClass);
|
||||
final String supDynName = serviceClass.getName().replace('.', '/');
|
||||
protected static <T extends Service> Class<? extends T> createLocalServiceClass(final String name, final Class<T> 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<Method> 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<Ljava/lang/String;>;", 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, "<clinit>", "()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, "<init>", "()V", null, null));
|
||||
//mv.setDebug(true);
|
||||
@@ -762,6 +885,10 @@ public abstract class Sncp {
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends Service> T createSimpleLocalService(final String name, final Class<T> 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 extends Service> T createLocalService(final String name, final Consumer<Runnable> executor, final ResourceFactory resourceFactory,
|
||||
final Class<T> serviceImplClass, final InetSocketAddress clientAddress, final Transport sameGroupTransport, final Collection<Transport> diffGroupTransports) {
|
||||
public static <T extends Service> T createLocalService(
|
||||
final String name,
|
||||
final Consumer<Runnable> executor,
|
||||
final ResourceFactory resourceFactory,
|
||||
final Class<T> serviceImplClass,
|
||||
final InetSocketAddress clientAddress,
|
||||
final String sncpGroup,
|
||||
final Set<String> groups,
|
||||
final AnyValue conf,
|
||||
final Transport sameGroupTransport,
|
||||
final Collection<Transport> 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<String> groups = new ArrayList<>();
|
||||
if (sameGroupTransport != null) groups.add(sameGroupTransport.getName());
|
||||
if (diffGroupTransports != null) {
|
||||
for (Transport t : diffGroupTransports) {
|
||||
groups.add(t.getName());
|
||||
}
|
||||
}
|
||||
// List<String> 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 extends Service> T createSimpleRemoteService(final String name, final Class<T> serviceTypeOrImplClass, final InetSocketAddress clientAddress, final Transport transport) {
|
||||
return createRemoteService(name, null, serviceTypeOrImplClass, clientAddress, (String) null, new HashSet<>(), (AnyValue) null, transport);
|
||||
}
|
||||
|
||||
/**
|
||||
* <blockquote><pre>
|
||||
* @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 <T> Service泛型
|
||||
* @param name 资源名
|
||||
* @param executor 线程池
|
||||
* @param serviceTypeOrImplClass Service类
|
||||
* @param clientAddress 本地IP地址
|
||||
* @param transport 通信组件
|
||||
* @param <T> 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 extends Service> T createRemoteService(final String name, final Consumer<Runnable> executor, final Class<T> serviceTypeOrImplClass,
|
||||
final InetSocketAddress clientAddress, final Transport transport) {
|
||||
public static <T extends Service> T createRemoteService(
|
||||
final String name,
|
||||
final Consumer<Runnable> executor,
|
||||
final Class<T> serviceTypeOrImplClass,
|
||||
final InetSocketAddress clientAddress,
|
||||
final String sncpGroup,
|
||||
final Set<String> 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<Ljava/lang/String;>;", 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, "<clinit>", "()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, "<init>", "()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);
|
||||
|
||||
@@ -162,7 +162,7 @@ public final class SncpClient {
|
||||
|
||||
protected final Consumer<Runnable> executor;
|
||||
|
||||
public <T extends Service> SncpClient(final String serviceName, final Class<T> serviceType, final T service, final Consumer<Runnable> executor,
|
||||
public <T extends Service> SncpClient(final String serviceName, final Class<T> serviceTypeOrImplClass, final T service, final Consumer<Runnable> 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<SncpAction> methodens = new ArrayList<>();
|
||||
//------------------------------------------------------------------------------
|
||||
for (java.lang.reflect.Method method : parseMethod(serviceClass)) {
|
||||
|
||||
@@ -38,15 +38,15 @@ public final class SncpServer extends Server<DLong, SncpContext, SncpRequest, Sn
|
||||
super.init(config);
|
||||
}
|
||||
|
||||
public void addSncpServlet(ServiceWrapper entry) {
|
||||
for (Class type : entry.getTypes()) {
|
||||
SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), entry.getName(), type, entry.getService());
|
||||
this.prepare.addServlet(sds, null, entry.getConf());
|
||||
public void addSncpServlet(Service sncpService) {
|
||||
for (Class type : Sncp.getResourceTypes(sncpService)) {
|
||||
SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), Sncp.getResourceName(sncpService), type, sncpService);
|
||||
this.prepare.addServlet(sds, null, Sncp.getConf(sncpService));
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends Service> void addSncpServlet(Class<T> serviceType, String name, T service, AnyValue conf) {
|
||||
SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), name, serviceType, service);
|
||||
public <T extends Service> void addSncpServlet(Class<T> serviceTypeClass, String name, T service, AnyValue conf) {
|
||||
SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), name, serviceTypeClass, service);
|
||||
this.prepare.addServlet(sds, null, conf);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user