diff --git a/src/main/java/org/redkale/boot/Application.java b/src/main/java/org/redkale/boot/Application.java index bc17a72c9..c91fbd8d0 100644 --- a/src/main/java/org/redkale/boot/Application.java +++ b/src/main/java/org/redkale/boot/Application.java @@ -391,7 +391,9 @@ public final class Application { Field field, Object attachment) { try { - field.set(srcObj, application); + if (field != null) { + field.set(srcObj, application); + } return application; } catch (Exception e) { logger.log(Level.SEVERE, "Resource inject error", e); @@ -423,7 +425,9 @@ public final class Application { boolean serv = RESNAME_SERVER_RESFACTORY.equals(resourceName) || resourceName.equalsIgnoreCase("server"); ResourceFactory rs = serv ? rf : (resourceName.isEmpty() ? application.resourceFactory : null); - field.set(srcObj, rs); + if (field != null) { + field.set(srcObj, rs); + } return rs; } catch (Exception e) { logger.log(Level.SEVERE, "Resource inject error", e); @@ -462,7 +466,9 @@ public final class Application { break; } } - field.set(srcObj, server); + if (field != null) { + field.set(srcObj, server); + } return server; } catch (Exception e) { logger.log(Level.SEVERE, "Resource inject error", e); @@ -501,7 +507,9 @@ public final class Application { break; } } - field.set(srcObj, server); + if (field != null) { + field.set(srcObj, server); + } return server; } catch (Exception e) { logger.log(Level.SEVERE, "Resource inject error", e); @@ -540,7 +548,9 @@ public final class Application { break; } } - field.set(srcObj, server); + if (field != null) { + field.set(srcObj, server); + } return server; } catch (Exception e) { logger.log(Level.SEVERE, "Resource inject error", e); @@ -578,7 +588,9 @@ public final class Application { builder.version(HttpClient.Version.HTTP_2); } java.net.http.HttpClient httpClient = builder.build(); - field.set(srcObj, httpClient); + if (field != null) { + field.set(srcObj, httpClient); + } rf.inject(resourceName, httpClient, null); // 给其可能包含@Resource的字段赋值; rf.register(resourceName, java.net.http.HttpClient.class, httpClient); return httpClient; @@ -606,7 +618,9 @@ public final class Application { Object attachment) { try { WebClient httpClient = WebClient.create(workExecutor, clientAsyncGroup); - field.set(srcObj, httpClient); + if (field != null) { + field.set(srcObj, httpClient); + } rf.inject(resourceName, httpClient, null); // 给其可能包含@Resource的字段赋值; rf.register(resourceName, WebClient.class, httpClient); return httpClient; @@ -640,7 +654,9 @@ public final class Application { || !Objects.equals(clusterAgent.getName(), resourceName) || messageAgent.isRpcFirst()) { HttpRpcClient rpcClient = messageAgent.getHttpRpcClient(); - field.set(srcObj, rpcClient); + if (field != null) { + field.set(srcObj, rpcClient); + } rf.inject(resourceName, rpcClient, null); // 给其可能包含@Resource的字段赋值; rf.register(resourceName, HttpRpcClient.class, rpcClient); return rpcClient; @@ -648,13 +664,17 @@ public final class Application { } if (clusterAgent == null) { HttpRpcClient rpcClient = new HttpLocalRpcClient(application, resourceName); - field.set(srcObj, rpcClient); + if (field != null) { + field.set(srcObj, rpcClient); + } rf.inject(resourceName, rpcClient, null); // 给其可能包含@Resource的字段赋值; rf.register(resourceName, HttpRpcClient.class, rpcClient); return rpcClient; } HttpRpcClient rpcClient = new HttpClusterRpcClient(application, resourceName, clusterAgent); - field.set(srcObj, rpcClient); + if (field != null) { + field.set(srcObj, rpcClient); + } rf.inject(resourceName, rpcClient, null); // 给其可能包含@Resource的字段赋值; rf.register(resourceName, HttpRpcClient.class, rpcClient); return rpcClient; diff --git a/src/main/java/org/redkale/boot/ModuleEngine.java b/src/main/java/org/redkale/boot/ModuleEngine.java index cd0fb2ee0..69fdd20f2 100644 --- a/src/main/java/org/redkale/boot/ModuleEngine.java +++ b/src/main/java/org/redkale/boot/ModuleEngine.java @@ -38,6 +38,18 @@ public abstract class ModuleEngine { this.environment = Objects.requireNonNull(application.getEnvironment()); } + public final ResourceFactory getResourceFactory() { + return resourceFactory; + } + + public final Environment getEnvironment() { + return environment; + } + + public final Application getApplication() { + return application; + } + /** * 判断模块的配置项合并策略, 返回null表示模块不识别此配置项 * diff --git a/src/main/java/org/redkale/boot/NodeAutoServiceLoader.java b/src/main/java/org/redkale/boot/NodeAutoServiceLoader.java new file mode 100644 index 000000000..079f23d08 --- /dev/null +++ b/src/main/java/org/redkale/boot/NodeAutoServiceLoader.java @@ -0,0 +1,123 @@ +/* + +*/ + +package org.redkale.boot; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.redkale.annotation.AutoLoad; +import org.redkale.asm.AsmMethodBoost; +import org.redkale.inject.ResourceFactory; +import org.redkale.inject.ResourceTypeLoader; +import org.redkale.mq.spi.MessageAgent; +import org.redkale.net.sncp.Sncp; +import org.redkale.service.Local; +import org.redkale.service.Service; +import org.redkale.util.Utility; + +/** + * + * @author zhangjx + */ +class NodeAutoServiceLoader implements ResourceTypeLoader { + + private final Logger logger = Logger.getLogger(getClass().getSimpleName()); + + private final NodeServer nodeServer; + + public NodeAutoServiceLoader(NodeServer nodeServer) { + this.nodeServer = nodeServer; + } + + @Override + public Object load( + ResourceFactory rf, + String srcResourceName, + final Object srcObj, + final String resourceName, + Field field, + final Object attachment) { + Application application = nodeServer.getApplication(); + final ResourceFactory appResFactory = application.getResourceFactory(); + Class serviceImplClass = Service.class; + try { + serviceImplClass = (Class) field.getType(); + if (serviceImplClass.getAnnotation(Local.class) == null) { + return null; + } + if ((srcObj instanceof Service) && Sncp.isRemote((Service) srcObj)) { + return null; // 远程模式不得注入 AutoLoad Service + } + boolean auto = true; + AutoLoad al = serviceImplClass.getAnnotation(AutoLoad.class); + if (al != null) { + auto = al.value(); + } + org.redkale.util.AutoLoad al2 = serviceImplClass.getAnnotation(org.redkale.util.AutoLoad.class); + if (al2 != null) { + auto = al2.value(); + } + if (auto && !Utility.isAbstractOrInterface(serviceImplClass)) { + return null; + } + + // ResourceFactory resfactory = (isSNCP() ? appResFactory : resourceFactory); + Service service; + if (Modifier.isFinal(serviceImplClass.getModifiers()) || Sncp.isComponent(serviceImplClass)) { + service = (Service) serviceImplClass.getConstructor().newInstance(); + } else if (Utility.isAbstractOrInterface(serviceImplClass)) { // 没有具体实现类 + AsmMethodBoost methodBoost = application.createAsmMethodBoost(true, serviceImplClass); + MessageAgent mqAgent = appResFactory.find("", MessageAgent.class); + service = Sncp.createRemoteService( + nodeServer.serverClassLoader, + resourceName, + serviceImplClass, + methodBoost, + appResFactory, + application.getSncpRpcGroups(), + nodeServer.sncpClient, + mqAgent, + null, + null); + } else { + AsmMethodBoost methodBoost = application.createAsmMethodBoost(false, serviceImplClass); + service = Sncp.createLocalService( + nodeServer.serverClassLoader, + resourceName, + serviceImplClass, + methodBoost, + appResFactory, + application.getSncpRpcGroups(), + nodeServer.sncpClient, + null, + null, + null); + } + appResFactory.register(resourceName, serviceImplClass, service); + + field.set(srcObj, service); + rf.inject(resourceName, service, nodeServer); // 给其可能包含@Resource的字段赋值; + if (!application.isCompileMode() && !Sncp.isRemote(service)) { + service.init(null); + } + logger.info("Load Service(" + (Sncp.isRemote(service) ? "Remote" : "@Local") + " @AutoLoad service = " + + serviceImplClass.getSimpleName() + ", resourceName = '" + resourceName + "')"); + return service; + } catch (Exception e) { + logger.log( + Level.SEVERE, + "Load @AutoLoad(false) Service inject " + serviceImplClass + " to " + srcObj + " error", + e); + return null; + } + } + + @Override + public Type resourceType() { + return Service.class; + } +} diff --git a/src/main/java/org/redkale/boot/NodeExpectServiceLoader.java b/src/main/java/org/redkale/boot/NodeExpectServiceLoader.java new file mode 100644 index 000000000..955482ac6 --- /dev/null +++ b/src/main/java/org/redkale/boot/NodeExpectServiceLoader.java @@ -0,0 +1,162 @@ +/* + +*/ + +package org.redkale.boot; + +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.redkale.annotation.Priority; +import org.redkale.asm.AsmMethodBoost; +import org.redkale.inject.ResourceFactory; +import org.redkale.inject.ResourceTypeLoader; +import org.redkale.mq.spi.MessageAgent; +import org.redkale.net.http.WebSocketServlet; +import org.redkale.net.sncp.Sncp; +import org.redkale.net.sncp.SncpRpcGroups; +import org.redkale.service.Service; +import org.redkale.util.RedkaleClassLoader; +import org.redkale.util.RedkaleException; + +/** + * + * @author zhangjx + */ +class NodeExpectServiceLoader implements ResourceTypeLoader { + + private final Logger logger = Logger.getLogger(getClass().getSimpleName()); + + private final NodeServer nodeServer; + + private final Class type; + + private final Class serviceImplClass; + + private final AtomicInteger serviceCount; + + private final SncpRpcGroups rpcGroups; + + private final ClassFilter.FilterEntry entry; + + private final String group; + + private final boolean localMode; + + public NodeExpectServiceLoader( + NodeServer nodeServer, + Class type, + Class serviceImplClass, + AtomicInteger serviceCount, + SncpRpcGroups rpcGroups, + ClassFilter.FilterEntry entry, + String group, + boolean localMode) { + this.nodeServer = nodeServer; + this.type = type; + this.serviceImplClass = serviceImplClass; + this.serviceCount = serviceCount; + this.rpcGroups = rpcGroups; + this.entry = entry; + this.group = group; + this.localMode = localMode; + } + + @Override + public Object load( + ResourceFactory rf, + String srcResourceName, + final Object srcObj, + final String resourceName, + Field field, + final Object attachment) { + try { + Application application = nodeServer.getApplication(); + final ResourceFactory resourceFactory = nodeServer.getResourceFactory(); + final ResourceFactory appResourceFactory = application.getResourceFactory(); + ResourceFactory regFactory = nodeServer.isSNCP() ? application.getResourceFactory() : resourceFactory; + + if (Sncp.loadRemoteMethodActions(Sncp.getResourceType(serviceImplClass)) + .isEmpty() + && (serviceImplClass.getAnnotation(Priority.class) == null + && serviceImplClass.getAnnotation(javax.annotation.Priority.class) + == null)) { // class没有可用的方法且没有标记启动优先级的, 通常为BaseService + if (!serviceImplClass.getName().startsWith("org.redkale.") + && !serviceImplClass.getSimpleName().contains("Base")) { + logger.log( + Level.FINE, + serviceImplClass + " cannot load because not found less one public non-final method"); + } + return null; + } + RedkaleClassLoader.putReflectionPublicMethods(serviceImplClass.getName()); + MessageAgent mqAgent = nodeServer.getMessageAgent(entry.getProperty()); + Service service; + if (Sncp.isComponent(serviceImplClass)) { // Component + RedkaleClassLoader.putReflectionPublicConstructors(serviceImplClass, serviceImplClass.getName()); + if (!nodeServer.acceptsComponent(serviceImplClass)) { + return null; + } + service = serviceImplClass.getDeclaredConstructor().newInstance(); + } else if (srcObj instanceof WebSocketServlet || localMode) { // 本地模式 + AsmMethodBoost methodBoost = application.createAsmMethodBoost(false, serviceImplClass); + service = Sncp.createLocalService( + nodeServer.serverClassLoader, + resourceName, + serviceImplClass, + methodBoost, + appResourceFactory, + rpcGroups, + nodeServer.sncpClient, + mqAgent, + group, + entry.getProperty()); + } else { + AsmMethodBoost methodBoost = application.createAsmMethodBoost(true, serviceImplClass); + service = Sncp.createRemoteService( + nodeServer.serverClassLoader, + resourceName, + serviceImplClass, + methodBoost, + appResourceFactory, + rpcGroups, + nodeServer.sncpClient, + mqAgent, + group, + entry.getProperty()); + } + final Class restype = Sncp.getResourceType(service); + if (rf.find(resourceName, restype) == null) { + regFactory.register(resourceName, restype, service); + } else if (nodeServer.isSNCP() && !entry.isAutoload()) { + throw new RedkaleException(restype.getSimpleName() + "(class:" + serviceImplClass.getName() + ", name:" + + resourceName + ", group:" + group + ") is repeat."); + } + if (Sncp.isRemote(service)) { + nodeServer.remoteServices.add(service); + if (mqAgent != null) { + nodeServer.sncpRemoteAgents.put(mqAgent.getName(), mqAgent); + } + } else { + if (field != null) { + rf.inject(resourceName, service); // 动态加载的Service也存在按需加载的注入资源 + } + nodeServer.localServices.add(service); + if (!Sncp.isComponent(service)) { + nodeServer.servletServices.add(service); + } + } + serviceCount.incrementAndGet(); + return service; + } catch (Exception e) { + throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); + } + } + + @Override + public Type resourceType() { + return type; + } +} diff --git a/src/main/java/org/redkale/boot/NodeHttpServer.java b/src/main/java/org/redkale/boot/NodeHttpServer.java index 072863659..6fd542834 100644 --- a/src/main/java/org/redkale/boot/NodeHttpServer.java +++ b/src/main/java/org/redkale/boot/NodeHttpServer.java @@ -5,8 +5,6 @@ */ package org.redkale.boot; -import static org.redkale.boot.Application.RESNAME_SNCP_ADDRESS; - import java.lang.annotation.Annotation; import java.lang.reflect.*; import java.net.*; @@ -16,11 +14,8 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; import java.util.stream.Stream; import org.redkale.annotation.*; -import org.redkale.asm.AsmMethodBoost; import org.redkale.boot.ClassFilter.FilterEntry; import org.redkale.cluster.spi.ClusterAgent; -import org.redkale.inject.ResourceFactory; -import org.redkale.inject.ResourceTypeLoader; import org.redkale.mq.spi.MessageAgent; import org.redkale.net.*; import org.redkale.net.http.*; @@ -124,7 +119,7 @@ public class NodeHttpServer extends NodeServer { @Override protected void loadService(ClassFilter serviceFilter) throws Exception { super.loadService(serviceFilter); - initWebSocketService(); + resourceFactory.register(new NodeWebSocketNodeLoader(this)); } @Override @@ -142,105 +137,6 @@ public class NodeHttpServer extends NodeServer { } } - private void initWebSocketService() { - final NodeServer self = this; - final ResourceFactory regFactory = application.getResourceFactory(); - resourceFactory.register(new ResourceTypeLoader() { - - @Override - public Object load( - ResourceFactory rf, - String srcResourceName, - Object srcObj, - String resourceName, - Field field, - Object attachment) { // 主要用于单点的服务 - try { - if (!(srcObj instanceof WebSocketServlet)) { - return null; - } - ResourceTypeLoader loader = null; - ResourceFactory sncpResFactory = null; - for (NodeServer ns : application.servers) { - if (!ns.isSNCP()) { - continue; - } - sncpResFactory = ns.resourceFactory; - loader = sncpResFactory.findTypeLoader(WebSocketNode.class, field); - if (loader != null) { - break; - } - } - Service nodeService = null; - if (loader != null) { - nodeService = (Service) - loader.load(sncpResFactory, srcResourceName, srcObj, resourceName, field, attachment); - } - regFactory.lock(); - try { - if (nodeService == null) { - nodeService = (Service) rf.find(resourceName, WebSocketNode.class); - } - if (sncpResFactory != null - && resourceFactory.find(RESNAME_SNCP_ADDRESS, String.class) == null) { - resourceFactory.register( - RESNAME_SNCP_ADDRESS, - InetSocketAddress.class, - sncpResFactory.find(RESNAME_SNCP_ADDRESS, InetSocketAddress.class)); - resourceFactory.register( - RESNAME_SNCP_ADDRESS, - SocketAddress.class, - sncpResFactory.find(RESNAME_SNCP_ADDRESS, SocketAddress.class)); - resourceFactory.register( - RESNAME_SNCP_ADDRESS, - String.class, - sncpResFactory.find(RESNAME_SNCP_ADDRESS, String.class)); - } - if (nodeService == null) { - MessageAgent messageAgent = null; - try { - Field c = WebSocketServlet.class.getDeclaredField("messageAgent"); - RedkaleClassLoader.putReflectionField("messageAgent", c); - c.setAccessible(true); - messageAgent = (MessageAgent) c.get(srcObj); - } catch (Exception ex) { - logger.log(Level.WARNING, "WebSocketServlet getMessageAgent error", ex); - } - AsmMethodBoost methodBoost = - application.createAsmMethodBoost(false, WebSocketNodeService.class); - nodeService = Sncp.createLocalService( - serverClassLoader, - resourceName, - WebSocketNodeService.class, - methodBoost, - application.getResourceFactory(), - application.getSncpRpcGroups(), - sncpClient, - messageAgent, - (String) null, - (AnyValue) null); - regFactory.register(resourceName, WebSocketNode.class, nodeService); - } - resourceFactory.inject(resourceName, nodeService, self); - field.set(srcObj, nodeService); - logger.fine("Load Service " + nodeService); - return nodeService; - } finally { - regFactory.unlock(); - } - } catch (Exception e) { - logger.log(Level.SEVERE, "WebSocketNode inject error", e); - throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); - } - } - - @Override - public Type resourceType() { - return WebSocketNode.class; - } - }); - } - @SuppressWarnings("unchecked") protected void loadHttpFilter(final ClassFilter classFilter) throws Exception { final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null; diff --git a/src/main/java/org/redkale/boot/NodeServer.java b/src/main/java/org/redkale/boot/NodeServer.java index 57b76ac6f..f3443116b 100644 --- a/src/main/java/org/redkale/boot/NodeServer.java +++ b/src/main/java/org/redkale/boot/NodeServer.java @@ -5,8 +5,6 @@ */ package org.redkale.boot; -import static org.redkale.boot.Application.*; - import java.io.*; import java.lang.annotation.Annotation; import java.lang.reflect.*; @@ -18,19 +16,15 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.*; import org.redkale.annotation.*; -import org.redkale.annotation.AutoLoad; import org.redkale.annotation.Command; -import org.redkale.asm.AsmMethodBoost; +import static org.redkale.boot.Application.*; import org.redkale.boot.ClassFilter.FilterEntry; import org.redkale.cluster.spi.ClusterAgent; import org.redkale.inject.ResourceFactory; -import org.redkale.inject.ResourceTypeLoader; import org.redkale.mq.spi.MessageAgent; import org.redkale.net.*; import org.redkale.net.Filter; import org.redkale.net.client.ClientAddress; -import org.redkale.net.http.*; -import org.redkale.net.http.WebSocketNodeService; import org.redkale.net.sncp.*; import org.redkale.service.*; import org.redkale.source.*; @@ -202,7 +196,12 @@ public abstract class NodeServer { 1000); } - registerResTypeLoader(); // 给DataSource、CacheSource注册依赖注入时的监听回调事件。 + // --------------------- 注册 Local AutoLoad(false) Service --------------------- + resourceFactory.register(new NodeAutoServiceLoader(this)); + // ----------------------------- 注册 WebSocketNode ----------------------------- + resourceFactory.register(new NodeWebSocketNodeLoader(this)); + + // 过滤类 String interceptorClass = this.serverConf.getValue("interceptor", ""); if (!interceptorClass.isEmpty()) { Class clazz = serverClassLoader.loadClass(interceptorClass); @@ -265,305 +264,6 @@ public abstract class NodeServer { protected abstract void loadServlet(ClassFilter servletFilter) throws Exception; - private void registerResTypeLoader() { - // --------------------- 注册 Local AutoLoad(false) Service --------------------- - resourceFactory.register(new ResourceTypeLoader() { - @Override - public Object load( - ResourceFactory rf, - String srcResourceName, - final Object srcObj, - final String resourceName, - Field field, - final Object attachment) { - return loadResourceService(rf, srcResourceName, srcObj, resourceName, field, attachment); - } - - @Override - public Type resourceType() { - return Service.class; - } - }); - // ----------------------------- 注册 WebSocketNode ----------------------------- - final NodeServer self = this; - final ResourceFactory appResFactory = application.getResourceFactory(); - resourceFactory.register(new ResourceTypeLoader() { - @Override - public Object load( - ResourceFactory rf, - String srcResourceName, - final Object srcObj, - final String resourceName, - Field field, - final Object attachment) { - try { - if ((srcObj instanceof Service) && Sncp.isRemote((Service) srcObj)) { - return null; // 远程模式不得注入 - } - Service nodeService = rf.find(resourceName, WebSocketNode.class); - if (nodeService == null) { - final HashSet groups = new HashSet<>(); - if (groups.isEmpty() && isSNCP() && NodeServer.this.sncpGroup != null) { - groups.add(NodeServer.this.sncpGroup); - } - AsmMethodBoost methodBoost = - application.createAsmMethodBoost(false, WebSocketNodeService.class); - nodeService = Sncp.createLocalService( - serverClassLoader, - resourceName, - WebSocketNodeService.class, - methodBoost, - application.getResourceFactory(), - application.getSncpRpcGroups(), - sncpClient, - null, - (String) null, - (AnyValue) null); - (isSNCP() ? appResFactory : resourceFactory) - .register(resourceName, WebSocketNode.class, nodeService); - ((org.redkale.net.http.WebSocketNodeService) nodeService).setName(resourceName); - } - resourceFactory.inject(resourceName, nodeService, self); - field.set(srcObj, nodeService); - if (Sncp.isRemote(nodeService)) { - remoteServices.add(nodeService); - } else { - rf.inject(resourceName, nodeService); // 动态加载的Service也存在按需加载的注入资源 - localServices.add(nodeService); - if (!Sncp.isComponent(nodeService)) { - servletServices.add(nodeService); - } - } - return nodeService; - } catch (Exception e) { - logger.log(Level.SEVERE, "WebSocketNode inject error", e); - throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); - } - } - - @Override - public Type resourceType() { - return WebSocketNode.class; - } - - @Override - public boolean autoNone() { - return false; - } - }); - } - - // Service.class的ResourceTypeLoader - private Object loadResourceService( - ResourceFactory rf, - String srcResourceName, - Object srcObj, - String resourceName, - Field field, - Object attachment) { - final NodeServer self = this; - final ResourceFactory appResFactory = application.getResourceFactory(); - Class serviceImplClass = Service.class; - try { - serviceImplClass = (Class) field.getType(); - if (serviceImplClass.getAnnotation(Local.class) == null) { - return null; - } - if ((srcObj instanceof Service) && Sncp.isRemote((Service) srcObj)) { - return null; // 远程模式不得注入 AutoLoad Service - } - boolean auto = true; - AutoLoad al = serviceImplClass.getAnnotation(AutoLoad.class); - if (al != null) { - auto = al.value(); - } - org.redkale.util.AutoLoad al2 = serviceImplClass.getAnnotation(org.redkale.util.AutoLoad.class); - if (al2 != null) { - auto = al2.value(); - } - if (auto && !Utility.isAbstractOrInterface(serviceImplClass)) { - return null; - } - - // ResourceFactory resfactory = (isSNCP() ? appResFactory : resourceFactory); - Service service; - if (Modifier.isFinal(serviceImplClass.getModifiers()) || Sncp.isComponent(serviceImplClass)) { - service = (Service) serviceImplClass.getConstructor().newInstance(); - } else if (Utility.isAbstractOrInterface(serviceImplClass)) { // 没有具体实现类 - AsmMethodBoost methodBoost = application.createAsmMethodBoost(true, serviceImplClass); - MessageAgent mqAgent = appResFactory.find("", MessageAgent.class); - service = Sncp.createRemoteService( - serverClassLoader, - resourceName, - serviceImplClass, - methodBoost, - appResFactory, - application.getSncpRpcGroups(), - this.sncpClient, - mqAgent, - null, - null); - } else { - AsmMethodBoost methodBoost = application.createAsmMethodBoost(false, serviceImplClass); - service = Sncp.createLocalService( - serverClassLoader, - resourceName, - serviceImplClass, - methodBoost, - appResFactory, - application.getSncpRpcGroups(), - sncpClient, - null, - null, - null); - } - appResFactory.register(resourceName, serviceImplClass, service); - - field.set(srcObj, service); - rf.inject(resourceName, service, self); // 给其可能包含@Resource的字段赋值; - if (!application.isCompileMode() && !Sncp.isRemote(service)) { - service.init(null); - } - logger.info("Load Service(" + (Sncp.isRemote(service) ? "Remote" : "@Local") + " @AutoLoad service = " - + serviceImplClass.getSimpleName() + ", resourceName = '" + resourceName + "')"); - return service; - } catch (Exception e) { - logger.log( - Level.SEVERE, - "Load @AutoLoad(false) Service inject " + serviceImplClass + " to " + srcObj + " error", - e); - return null; - } - } - - private class ExpectServiceLoader implements ResourceTypeLoader { - - private final Class type; - - private final Class serviceImplClass; - - private final AtomicInteger serviceCount; - - private final SncpRpcGroups rpcGroups; - - private final FilterEntry entry; - - private final String group; - - private final boolean localMode; - - public ExpectServiceLoader( - Class type, - Class serviceImplClass, - AtomicInteger serviceCount, - SncpRpcGroups rpcGroups, - FilterEntry entry, - String group, - boolean localMode) { - this.type = type; - this.serviceImplClass = serviceImplClass; - this.serviceCount = serviceCount; - this.rpcGroups = rpcGroups; - this.entry = entry; - this.group = group; - this.localMode = localMode; - } - - @Override - public Object load( - ResourceFactory rf, - String srcResourceName, - final Object srcObj, - final String resourceName, - Field field, - final Object attachment) { - try { - final ResourceFactory appResourceFactory = application.getResourceFactory(); - ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : resourceFactory; - - if (Sncp.loadRemoteMethodActions(Sncp.getResourceType(serviceImplClass)) - .isEmpty() - && (serviceImplClass.getAnnotation(Priority.class) == null - && serviceImplClass.getAnnotation(javax.annotation.Priority.class) - == null)) { // class没有可用的方法且没有标记启动优先级的, 通常为BaseService - if (!serviceImplClass.getName().startsWith("org.redkale.") - && !serviceImplClass.getSimpleName().contains("Base")) { - logger.log( - Level.FINE, - serviceImplClass + " cannot load because not found less one public non-final method"); - } - return null; - } - RedkaleClassLoader.putReflectionPublicMethods(serviceImplClass.getName()); - MessageAgent mqAgent = getMessageAgent(entry.getProperty()); - Service service; - if (Sncp.isComponent(serviceImplClass)) { // Component - RedkaleClassLoader.putReflectionPublicConstructors(serviceImplClass, serviceImplClass.getName()); - if (!acceptsComponent(serviceImplClass)) { - return null; - } - service = serviceImplClass.getDeclaredConstructor().newInstance(); - } else if (srcObj instanceof WebSocketServlet || localMode) { // 本地模式 - AsmMethodBoost methodBoost = application.createAsmMethodBoost(false, serviceImplClass); - service = Sncp.createLocalService( - serverClassLoader, - resourceName, - serviceImplClass, - methodBoost, - appResourceFactory, - rpcGroups, - sncpClient, - mqAgent, - group, - entry.getProperty()); - } else { - AsmMethodBoost methodBoost = application.createAsmMethodBoost(true, serviceImplClass); - service = Sncp.createRemoteService( - serverClassLoader, - resourceName, - serviceImplClass, - methodBoost, - appResourceFactory, - rpcGroups, - sncpClient, - mqAgent, - group, - entry.getProperty()); - } - final Class restype = Sncp.getResourceType(service); - if (rf.find(resourceName, restype) == null) { - regFactory.register(resourceName, restype, service); - } else if (isSNCP() && !entry.isAutoload()) { - throw new RedkaleException(restype.getSimpleName() + "(class:" + serviceImplClass.getName() - + ", name:" + resourceName + ", group:" + group + ") is repeat."); - } - if (Sncp.isRemote(service)) { - remoteServices.add(service); - if (mqAgent != null) { - sncpRemoteAgents.put(mqAgent.getName(), mqAgent); - } - } else { - if (field != null) { - rf.inject(resourceName, service); // 动态加载的Service也存在按需加载的注入资源 - } - localServices.add(service); - if (!Sncp.isComponent(service)) { - servletServices.add(service); - } - } - serviceCount.incrementAndGet(); - return service; - } catch (Exception e) { - throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); - } - } - - @Override - public Type resourceType() { - return type; - } - } - @SuppressWarnings("unchecked") protected void loadService(ClassFilter serviceFilter) throws Exception { Objects.requireNonNull(serviceFilter); @@ -618,12 +318,12 @@ public abstract class NodeServer { if (entry.isExpect()) { Class t = ResourceFactory.getResourceType(entry.getType()); if (resourceFactory.findResourceTypeLoader(t) == null) { - resourceFactory.register(new ExpectServiceLoader( - t, serviceImplClass, serviceCount, rpcGroups, entry, group, localMode)); + resourceFactory.register(new NodeExpectServiceLoader( + this, t, serviceImplClass, serviceCount, rpcGroups, entry, group, localMode)); } } else { - ExpectServiceLoader resourceLoader = new ExpectServiceLoader( - serviceImplClass, serviceImplClass, serviceCount, rpcGroups, entry, group, localMode); + NodeExpectServiceLoader resourceLoader = new NodeExpectServiceLoader( + this, serviceImplClass, serviceImplClass, serviceCount, rpcGroups, entry, group, localMode); resourceLoader.load(resourceFactory, null, null, entry.getName(), null, false); } } diff --git a/src/main/java/org/redkale/boot/NodeWebSocketNodeLoader.java b/src/main/java/org/redkale/boot/NodeWebSocketNodeLoader.java new file mode 100644 index 000000000..bb2425e9a --- /dev/null +++ b/src/main/java/org/redkale/boot/NodeWebSocketNodeLoader.java @@ -0,0 +1,206 @@ +/* + +*/ + +package org.redkale.boot; + +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.HashSet; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.redkale.asm.AsmMethodBoost; +import static org.redkale.boot.Application.RESNAME_SNCP_ADDRESS; +import org.redkale.inject.ResourceFactory; +import org.redkale.inject.ResourceTypeLoader; +import org.redkale.mq.spi.MessageAgent; +import org.redkale.net.http.WebSocketNode; +import org.redkale.net.http.WebSocketNodeService; +import org.redkale.net.http.WebSocketServlet; +import org.redkale.net.sncp.Sncp; +import org.redkale.service.Service; +import org.redkale.util.AnyValue; +import org.redkale.util.RedkaleClassLoader; +import org.redkale.util.RedkaleException; + +/** + * + * @author zhangjx + */ +class NodeWebSocketNodeLoader implements ResourceTypeLoader { + + private final Logger logger = Logger.getLogger(getClass().getSimpleName()); + + private final NodeServer nodeServer; + + public NodeWebSocketNodeLoader(NodeServer nodeServer) { + this.nodeServer = nodeServer; + } + + @Override + public Object load( + ResourceFactory rf, + String srcResourceName, + Object srcObj, + String resourceName, + Field field, + Object attachment) { + if (srcObj instanceof WebSocketServlet) { + return loadInServlet(rf, srcResourceName, srcObj, resourceName, field, attachment); + } else { + return loadInService(rf, srcResourceName, srcObj, resourceName, field, attachment); + } + } + + private Object loadInService( + ResourceFactory rf, + String srcResourceName, + Object srcObj, + String resourceName, + Field field, + Object attachment) { + try { + if ((srcObj instanceof Service) && Sncp.isRemote((Service) srcObj)) { + return null; // 远程模式不得注入 + } + Application application = nodeServer.getApplication(); + final ResourceFactory appResFactory = application.getResourceFactory(); + final ResourceFactory resourceFactory = nodeServer.getResourceFactory(); + Service nodeService = rf.find(resourceName, WebSocketNode.class); + if (nodeService == null) { + final HashSet groups = new HashSet<>(); + if (groups.isEmpty() && nodeServer.isSNCP() && nodeServer.sncpGroup != null) { + groups.add(nodeServer.sncpGroup); + } + AsmMethodBoost methodBoost = application.createAsmMethodBoost(false, WebSocketNodeService.class); + nodeService = Sncp.createLocalService( + nodeServer.serverClassLoader, + resourceName, + WebSocketNodeService.class, + methodBoost, + application.getResourceFactory(), + application.getSncpRpcGroups(), + nodeServer.sncpClient, + null, + (String) null, + (AnyValue) null); + (nodeServer.isSNCP() ? appResFactory : resourceFactory) + .register(resourceName, WebSocketNode.class, nodeService); + ((org.redkale.net.http.WebSocketNodeService) nodeService).setName(resourceName); + } + resourceFactory.inject(resourceName, nodeService, nodeServer); + if (field != null) { + field.set(srcObj, nodeService); + } + if (Sncp.isRemote(nodeService)) { + nodeServer.remoteServices.add(nodeService); + } else { + rf.inject(resourceName, nodeService); // 动态加载的Service也存在按需加载的注入资源 + nodeServer.localServices.add(nodeService); + if (!Sncp.isComponent(nodeService)) { + nodeServer.servletServices.add(nodeService); + } + } + return nodeService; + } catch (Exception e) { + logger.log(Level.SEVERE, "WebSocketNode inject error", e); + throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); + } + } + + private Object loadInServlet( + ResourceFactory rf, + String srcResourceName, + Object srcObj, + String resourceName, + Field field, + Object attachment) { // 主要用于单点的服务 + try { + if (!(srcObj instanceof WebSocketServlet)) { + return null; + } + Application application = nodeServer.getApplication(); + final ResourceFactory regFactory = application.getResourceFactory(); + final ResourceFactory resourceFactory = nodeServer.getResourceFactory(); + ResourceTypeLoader loader = null; + ResourceFactory sncpResFactory = null; + for (NodeServer ns : application.servers) { + if (!ns.isSNCP()) { + continue; + } + sncpResFactory = ns.resourceFactory; + loader = sncpResFactory.findTypeLoader(WebSocketNode.class, field); + if (loader != null) { + break; + } + } + Service nodeService = null; + if (loader != null) { + nodeService = + (Service) loader.load(sncpResFactory, srcResourceName, srcObj, resourceName, field, attachment); + } + regFactory.lock(); + try { + if (nodeService == null) { + nodeService = (Service) rf.find(resourceName, WebSocketNode.class); + } + if (sncpResFactory != null && resourceFactory.find(RESNAME_SNCP_ADDRESS, String.class) == null) { + resourceFactory.register( + RESNAME_SNCP_ADDRESS, + InetSocketAddress.class, + sncpResFactory.find(RESNAME_SNCP_ADDRESS, InetSocketAddress.class)); + resourceFactory.register( + RESNAME_SNCP_ADDRESS, + SocketAddress.class, + sncpResFactory.find(RESNAME_SNCP_ADDRESS, SocketAddress.class)); + resourceFactory.register( + RESNAME_SNCP_ADDRESS, + String.class, + sncpResFactory.find(RESNAME_SNCP_ADDRESS, String.class)); + } + if (nodeService == null) { + MessageAgent messageAgent = null; + try { + Field c = WebSocketServlet.class.getDeclaredField("messageAgent"); + RedkaleClassLoader.putReflectionField("messageAgent", c); + c.setAccessible(true); + messageAgent = (MessageAgent) c.get(srcObj); + } catch (Exception ex) { + logger.log(Level.WARNING, "WebSocketServlet getMessageAgent error", ex); + } + AsmMethodBoost methodBoost = application.createAsmMethodBoost(false, WebSocketNodeService.class); + nodeService = Sncp.createLocalService( + nodeServer.serverClassLoader, + resourceName, + WebSocketNodeService.class, + methodBoost, + application.getResourceFactory(), + application.getSncpRpcGroups(), + nodeServer.sncpClient, + messageAgent, + (String) null, + (AnyValue) null); + regFactory.register(resourceName, WebSocketNode.class, nodeService); + } + resourceFactory.inject(resourceName, nodeService, nodeServer); + if (field != null) { + field.set(srcObj, nodeService); + } + logger.fine("Load Service " + nodeService); + return nodeService; + } finally { + regFactory.unlock(); + } + } catch (Exception e) { + logger.log(Level.SEVERE, "WebSocketNode inject error", e); + throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); + } + } + + @Override + public Type resourceType() { + return WebSocketNode.class; + } +} diff --git a/src/main/java/org/redkale/cached/spi/CachedAction.java b/src/main/java/org/redkale/cached/spi/CachedAction.java index 8bf0836fb..02e816b1d 100644 --- a/src/main/java/org/redkale/cached/spi/CachedAction.java +++ b/src/main/java/org/redkale/cached/spi/CachedAction.java @@ -92,7 +92,7 @@ public class CachedAction { } void init(ResourceFactory resourceFactory, Object service) { - this.manager = resourceFactory.find(cached.getManager(), CachedManager.class); + this.manager = resourceFactory.load(cached.getManager(), CachedManager.class); String key = environment.getPropertyValue(cached.getKey()); this.templetKey = key; if (key.startsWith("@")) { // 动态加载缓存key生成器 diff --git a/src/main/java/org/redkale/cached/spi/CachedAsmMethodBoost.java b/src/main/java/org/redkale/cached/spi/CachedAsmMethodBoost.java index 4cfdf4cef..94dc93479 100644 --- a/src/main/java/org/redkale/cached/spi/CachedAsmMethodBoost.java +++ b/src/main/java/org/redkale/cached/spi/CachedAsmMethodBoost.java @@ -233,6 +233,7 @@ public class CachedAsmMethodBoost extends AsmMethodBoost { } } } + actionMap.forEach((field, action) -> { try { resourceFactory.inject(action); diff --git a/src/main/java/org/redkale/cached/spi/CachedKeyGeneratorLoader.java b/src/main/java/org/redkale/cached/spi/CachedKeyGeneratorLoader.java new file mode 100644 index 000000000..b6de94771 --- /dev/null +++ b/src/main/java/org/redkale/cached/spi/CachedKeyGeneratorLoader.java @@ -0,0 +1,79 @@ +/* + +*/ + +package org.redkale.cached.spi; + +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.Map; +import java.util.Objects; +import java.util.ServiceLoader; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.redkale.inject.ResourceFactory; +import org.redkale.inject.ResourceTypeLoader; +import org.redkale.service.Service; +import org.redkale.util.RedkaleException; + +/** + * + * @author zhangjx + */ +class CachedKeyGeneratorLoader implements ResourceTypeLoader { + + private final Logger logger = Logger.getLogger(getClass().getSimpleName()); + + private final CachedModuleEngine engine; + + private final Map generatorMap = new ConcurrentHashMap<>(); + + public CachedKeyGeneratorLoader(CachedModuleEngine engine) { + this.engine = engine; + } + + @Override + public Object load( + ResourceFactory rf, + String srcResourceName, + Object srcObj, + String resourceName, + Field field, + Object attachment) { + try { + CachedKeyGenerator generator = rf.find(resourceName, CachedKeyGenerator.class); + if (generator != null) { + return generator; + } + generator = generatorMap.computeIfAbsent(resourceName, n -> { + for (CachedKeyGenerator instance : ServiceLoader.load( + CachedKeyGenerator.class, engine.getApplication().getClassLoader())) { + if (Objects.equals(n, instance.name())) { + rf.inject(instance); + if (instance instanceof Service) { + ((Service) instance).init(null); + } + return instance; + } + } + return null; + }); + if (generator != null) { + rf.register(resourceName, CachedKeyGenerator.class, generator); + if (field != null) { + field.set(srcObj, generator); + } + } + return generator; + } catch (Exception e) { + logger.log(Level.SEVERE, CachedKeyGenerator.class.getSimpleName() + " inject error", e); + throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); + } + } + + @Override + public Type resourceType() { + return CachedKeyGenerator.class; + } +} diff --git a/src/main/java/org/redkale/cached/spi/CachedManagerLoader.java b/src/main/java/org/redkale/cached/spi/CachedManagerLoader.java new file mode 100644 index 000000000..8aad1e5ee --- /dev/null +++ b/src/main/java/org/redkale/cached/spi/CachedManagerLoader.java @@ -0,0 +1,81 @@ +/* + +*/ + +package org.redkale.cached.spi; + +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.redkale.cached.CachedManager; +import org.redkale.inject.ResourceFactory; +import org.redkale.inject.ResourceTypeLoader; +import org.redkale.service.Service; +import org.redkale.util.AnyValue; +import org.redkale.util.RedkaleException; + +/** + * + * @author zhangjx + */ +class CachedManagerLoader implements ResourceTypeLoader { + + private final Logger logger = Logger.getLogger(getClass().getSimpleName()); + private final CachedModuleEngine engine; + private Map configMap; + + public CachedManagerLoader(CachedModuleEngine engine, Map configMap) { + this.engine = engine; + this.configMap = configMap; + } + + @Override + public Object load( + ResourceFactory rf, + String srcResourceName, + Object srcObj, + String resourceName, + Field field, + Object attachment) { + try { + CachedManager manager = rf.find(resourceName, CachedManager.class); + if (manager != null) { + return manager; + } + AnyValue config = configMap.get(resourceName); + if (config == null) { + throw new RedkaleException( + "Not found " + CachedManager.class.getSimpleName() + "(name='" + resourceName + "') config"); + } + manager = engine.createManager(config); + if (manager != null) { + rf.register(resourceName, CachedManager.class, manager); + engine.cacheManagerMap.put(resourceName, new CachedModuleEngine.ManagerEntity(manager, config)); + if (!engine.getApplication().isCompileMode()) { + rf.inject(manager); + if (manager instanceof Service) { + ((Service) manager).init(config); + } + logger.info("Load " + CachedManager.class.getSimpleName() + " (type=" + + manager.getClass().getSimpleName() + ", resourceName='" + + resourceName + "', schema='" + + manager.getSchema() + "')"); + } + if (field != null) { + field.set(srcObj, manager); + } + } + return manager; + } catch (Exception e) { + logger.log(Level.SEVERE, CachedManager.class.getSimpleName() + " inject error", e); + throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); + } + } + + @Override + public Type resourceType() { + return CachedManager.class; + } +} diff --git a/src/main/java/org/redkale/cached/spi/CachedManagerService.java b/src/main/java/org/redkale/cached/spi/CachedManagerService.java index 01b96d5f0..63aabfd61 100644 --- a/src/main/java/org/redkale/cached/spi/CachedManagerService.java +++ b/src/main/java/org/redkale/cached/spi/CachedManagerService.java @@ -117,16 +117,16 @@ public class CachedManagerService implements CachedManager, Service { this.schema = conf.getValue("schema", DEFAULT_SCHEMA); if (this.enabled) { this.localSource.init(conf); - String remoteSourceName = conf.getValue("remote"); + String remoteSourceName = conf.getValue("remote", ""); if (remoteSource == null && remoteSourceName != null) { - this.broadcastable = conf.getBoolValue("broadcastable", true); CacheSource source = application.loadCacheSource(remoteSourceName, false); - if (source == null) { + if (source == null && !remoteSourceName.isEmpty()) { throw new RedkaleException("Not found CacheSource '" + remoteSourceName + "'"); } this.remoteSource = source; + this.broadcastable = conf.getBoolValue("broadcastable", true); } - if (remoteSource != null) { + if (remoteSource != null && this.broadcastable) { this.remoteListener = new CacheRemoteListener(); this.remoteSource.subscribe(CachedEventMessage.class, remoteListener, getChannelTopic()); } diff --git a/src/main/java/org/redkale/cached/spi/CachedModuleEngine.java b/src/main/java/org/redkale/cached/spi/CachedModuleEngine.java index 74f03480e..af222d968 100644 --- a/src/main/java/org/redkale/cached/spi/CachedModuleEngine.java +++ b/src/main/java/org/redkale/cached/spi/CachedModuleEngine.java @@ -3,26 +3,19 @@ */ package org.redkale.cached.spi; -import java.lang.reflect.Field; -import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.ServiceLoader; import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Level; import org.redkale.asm.AsmMethodBoost; import org.redkale.boot.Application; import org.redkale.boot.ModuleEngine; import org.redkale.cached.CachedManager; -import org.redkale.inject.ResourceFactory; -import org.redkale.inject.ResourceTypeLoader; import org.redkale.service.Service; import org.redkale.util.AnyValue; -import org.redkale.util.AnyValueWriter; import org.redkale.util.InstanceProvider; import org.redkale.util.RedkaleClassLoader; import org.redkale.util.RedkaleException; @@ -40,7 +33,7 @@ public class CachedModuleEngine extends ModuleEngine { protected static final String CONFIG_NAME = "cached"; // 全局缓存管理器 - private ConcurrentHashMap cacheManagerMap = new ConcurrentHashMap<>(); + protected ConcurrentHashMap cacheManagerMap = new ConcurrentHashMap<>(); public CachedModuleEngine(Application application) { super(application); @@ -81,7 +74,7 @@ public class CachedModuleEngine extends ModuleEngine { // 设置缓存管理器 AnyValue[] configs = application.getAppConfig().getAnyValues(CONFIG_NAME); if (configs == null || configs.length == 0) { - configs = new AnyValue[] {new AnyValueWriter()}; + configs = new AnyValue[] {AnyValue.create()}; } Map configMap = new HashMap<>(); for (AnyValue config : configs) { @@ -92,94 +85,8 @@ public class CachedModuleEngine extends ModuleEngine { } configMap.put(name, config); } - this.resourceFactory.register(new ResourceTypeLoader() { - - @Override - public Object load( - ResourceFactory rf, - String srcResourceName, - Object srcObj, - String resourceName, - Field field, - Object attachment) { - try { - CachedManager manager = rf.find(resourceName, CachedManager.class); - if (manager != null) { - return manager; - } - AnyValue config = configMap.get(resourceName); - if (config == null) { - throw new RedkaleException("Not found " + CachedManager.class.getSimpleName() + "(name='" - + resourceName + "') config"); - } - manager = createManager(config); - if (manager != null) { - rf.register(resourceName, CachedManager.class, manager); - cacheManagerMap.put(resourceName, new ManagerEntity(manager, config)); - if (!application.isCompileMode()) { - rf.inject(manager); - if (manager instanceof Service) { - ((Service) manager).init(config); - } - } - } - return manager; - } catch (Exception e) { - logger.log(Level.SEVERE, CachedManager.class.getSimpleName() + " inject error", e); - throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); - } - } - - @Override - public Type resourceType() { - return CachedManager.class; - } - }); - - ConcurrentHashMap generatorMap = new ConcurrentHashMap<>(); - this.resourceFactory.register(new ResourceTypeLoader() { - - @Override - public Object load( - ResourceFactory rf, - String srcResourceName, - Object srcObj, - String resourceName, - Field field, - Object attachment) { - try { - CachedKeyGenerator generator = rf.find(resourceName, CachedKeyGenerator.class); - if (generator != null) { - return generator; - } - generator = generatorMap.computeIfAbsent(resourceName, n -> { - for (CachedKeyGenerator instance : - ServiceLoader.load(CachedKeyGenerator.class, application.getClassLoader())) { - if (Objects.equals(n, instance.name())) { - rf.inject(instance); - if (instance instanceof Service) { - ((Service) instance).init(null); - } - return instance; - } - } - return null; - }); - if (generator != null) { - rf.register(resourceName, CachedKeyGenerator.class, generator); - } - return generator; - } catch (Exception e) { - logger.log(Level.SEVERE, CachedKeyGenerator.class.getSimpleName() + " inject error", e); - throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); - } - } - - @Override - public Type resourceType() { - return CachedKeyGenerator.class; - } - }); + this.resourceFactory.register(new CachedManagerLoader(this, configMap)); + this.resourceFactory.register(new CachedKeyGeneratorLoader(this)); } /** @@ -198,7 +105,7 @@ public class CachedModuleEngine extends ModuleEngine { } } - private CachedManager createManager(AnyValue conf) { + protected CachedManager createManager(AnyValue conf) { Iterator it = ServiceLoader.load( CachedManagerProvider.class, application.getClassLoader()) .iterator(); diff --git a/src/main/java/org/redkale/inject/ResourceFactory.java b/src/main/java/org/redkale/inject/ResourceFactory.java index 5133d29ce..568b82e1b 100644 --- a/src/main/java/org/redkale/inject/ResourceFactory.java +++ b/src/main/java/org/redkale/inject/ResourceFactory.java @@ -686,6 +686,32 @@ public final class ResourceFactory { return null; } + public A load(Class clazz) { + return load("", clazz); + } + + public A load(String name, Type clazz) { + A val = find(name, clazz); + if (val == null) { + ResourceTypeLoader loader = findResourceTypeLoader(clazz); + if (loader != null) { + val = (A) loader.load(this, null, null, name, null, null); + } + } + return val; + } + + public A load(String name, Class clazz) { + A val = find(name, clazz); + if (val == null) { + ResourceTypeLoader loader = findResourceTypeLoader(clazz); + if (loader != null) { + val = (A) loader.load(this, null, null, name, null, null); + } + } + return val; + } + public List query(Class clazz) { return query(new ArrayList<>(), clazz); } @@ -1097,7 +1123,7 @@ public final class ResourceFactory { return parent == null ? null : parent.findResourceTypeLoader(clazz); } - public ResourceTypeLoader findTypeLoader(Type ft, Field field) { + public ResourceTypeLoader findTypeLoader(Type ft, @Nullable Field field) { ResourceTypeLoader it = this.findMatchTypeLoader(ft, field); return it == null ? findRegxTypeLoader(ft, field) : it; } @@ -1109,7 +1135,7 @@ public final class ResourceFactory { return parent.parentRoot(); } - private ResourceTypeLoader findMatchTypeLoader(Type ft, Field field) { + private ResourceTypeLoader findMatchTypeLoader(Type ft, @Nullable Field field) { ResourceTypeLoader it = this.resTypeLoaderMap.get(ft); if (it == null && field != null) { it = this.resTypeLoaderMap.get(field.getType()); @@ -1120,7 +1146,7 @@ public final class ResourceFactory { return parent == null ? null : parent.findMatchTypeLoader(ft, field); } - private ResourceTypeLoader findRegxTypeLoader(Type ft, Field field) { + private ResourceTypeLoader findRegxTypeLoader(Type ft, @Nullable Field field) { if (field == null) { return null; } diff --git a/src/main/java/org/redkale/inject/ResourceTypeLoader.java b/src/main/java/org/redkale/inject/ResourceTypeLoader.java index 7c1028744..c597e0d35 100644 --- a/src/main/java/org/redkale/inject/ResourceTypeLoader.java +++ b/src/main/java/org/redkale/inject/ResourceTypeLoader.java @@ -4,6 +4,7 @@ package org.redkale.inject; import java.lang.reflect.Field; import java.lang.reflect.Type; +import org.redkale.annotation.Nullable; /** * 自定义注入加载器 @@ -14,18 +15,38 @@ import java.lang.reflect.Type; */ public interface ResourceTypeLoader { + /** + * 自定义的对象注入, 实现需要兼容Field为null的情况 + * + * @param factory ResourceFactory + * @param srcResourceName 依附对象的资源名 + * @param srcObj 依附对象 + * @param resourceName 资源名 + * @param field 字段对象 + * @param attachment + * @return Object + */ public Object load( ResourceFactory factory, - String srcResourceName, - Object srcObj, + @Nullable String srcResourceName, + @Nullable Object srcObj, String resourceName, - Field field, - Object attachment); - + @Nullable Field field, + @Nullable Object attachment); + /** + * 注入加载器对应的类型 + * + * @return 类型 + */ public Type resourceType(); - // 返回true: 表示调用ResourceLoader之后资源仍不存在,则会在ResourceFactory里注入默认值null。 - // 返回false: 表示资源不存在下次仍会调用ResourceLoader自行处理。 + /** + * 是否注入默认值null
+ * 返回true: 表示调用ResourceLoader之后资源仍不存在,则会在ResourceFactory里注入默认值null。
+ * 返回false: 表示资源不存在下次仍会调用{@link org.redkale.inject.ResourceTypeLoader}自行处理。
+ * + * @return 是否注入默认值null + */ default boolean autoNone() { return true; } diff --git a/src/main/java/org/redkale/source/spi/CacheSourceLoader.java b/src/main/java/org/redkale/source/spi/CacheSourceLoader.java new file mode 100644 index 000000000..c10786150 --- /dev/null +++ b/src/main/java/org/redkale/source/spi/CacheSourceLoader.java @@ -0,0 +1,78 @@ +/* + +*/ + +package org.redkale.source.spi; + +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.redkale.annotation.Resource; +import org.redkale.inject.ResourceFactory; +import org.redkale.inject.ResourceTypeLoader; +import org.redkale.net.Servlet; +import org.redkale.net.sncp.Sncp; +import org.redkale.service.Service; +import org.redkale.source.CacheSource; +import org.redkale.util.RedkaleException; + +/** + * + * @author zhangjx + */ +class CacheSourceLoader implements ResourceTypeLoader { + + private final Logger logger = Logger.getLogger(getClass().getSimpleName()); + + private final SourceModuleEngine engine; + + public CacheSourceLoader(SourceModuleEngine engine) { + this.engine = engine; + } + + @Override + public Object load( + ResourceFactory rf, + String srcResourceName, + Object srcObj, + String resourceName, + Field field, + Object attachment) { + try { + if ((srcObj instanceof Service) && Sncp.isRemote((Service) srcObj)) { + return null; // 远程模式不得注入 + } + if (srcObj instanceof Servlet) { + throw new RedkaleException("CacheSource cannot inject in Servlet " + srcObj); + } + final boolean ws = (srcObj instanceof org.redkale.net.http.WebSocketNodeService); + CacheSource source = engine.loadCacheSource(resourceName, ws); + if (field != null) { + field.set(srcObj, source); + Resource res = field.getAnnotation(Resource.class); + if (res != null && res.required() && source == null) { + throw new RedkaleException("CacheSource (resourceName = '" + resourceName + "') not found"); + } else { + logger.info("Load CacheSource (type = " + + (source == null ? null : source.getClass().getSimpleName()) + ", resourceName = '" + + resourceName + "')"); + } + } + return source; + } catch (Exception e) { + logger.log(Level.SEVERE, "DataSource inject error", e); + throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); + } + } + + @Override + public Type resourceType() { + return CacheSource.class; + } + + @Override + public boolean autoNone() { + return false; + } +} diff --git a/src/main/java/org/redkale/source/spi/DataSourceLoader.java b/src/main/java/org/redkale/source/spi/DataSourceLoader.java new file mode 100644 index 000000000..5c5c7f7f7 --- /dev/null +++ b/src/main/java/org/redkale/source/spi/DataSourceLoader.java @@ -0,0 +1,59 @@ +/* + +*/ + +package org.redkale.source.spi; + +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.redkale.inject.ResourceFactory; +import org.redkale.inject.ResourceTypeLoader; +import org.redkale.net.sncp.Sncp; +import org.redkale.service.Service; +import org.redkale.source.DataSource; +import org.redkale.util.RedkaleException; + +/** + * + * @author zhangjx + */ +class DataSourceLoader implements ResourceTypeLoader { + + private final Logger logger = Logger.getLogger(getClass().getSimpleName()); + + private final SourceModuleEngine engine; + + public DataSourceLoader(SourceModuleEngine engine) { + this.engine = engine; + } + + @Override + public Object load( + ResourceFactory rf, + String srcResourceName, + Object srcObj, + String resourceName, + Field field, + Object attachment) { + try { + if ((srcObj instanceof Service) && Sncp.isRemote((Service) srcObj)) { + return null; // 远程模式不得注入 + } + DataSource source = engine.loadDataSource(resourceName, false); + if (field != null) { + field.set(srcObj, source); + } + return source; + } catch (Exception e) { + logger.log(Level.SEVERE, "DataSource inject to " + srcObj + " error", e); + throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); + } + } + + @Override + public Type resourceType() { + return DataSource.class; + } +} diff --git a/src/main/java/org/redkale/source/spi/DataSqlMapperLoader.java b/src/main/java/org/redkale/source/spi/DataSqlMapperLoader.java new file mode 100644 index 000000000..97a1be1a3 --- /dev/null +++ b/src/main/java/org/redkale/source/spi/DataSqlMapperLoader.java @@ -0,0 +1,70 @@ +/* + +*/ + +package org.redkale.source.spi; + +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.redkale.inject.ResourceFactory; +import org.redkale.inject.ResourceTypeLoader; +import org.redkale.net.sncp.Sncp; +import org.redkale.service.Service; +import org.redkale.source.DataSource; +import org.redkale.source.DataSqlMapper; +import org.redkale.source.DataSqlSource; +import org.redkale.util.RedkaleException; + +/** + * + * @author zhangjx + */ +class DataSqlMapperLoader implements ResourceTypeLoader { + + private final Logger logger = Logger.getLogger(getClass().getSimpleName()); + + private final SourceModuleEngine engine; + + public DataSqlMapperLoader(SourceModuleEngine engine) { + this.engine = engine; + } + + @Override + public Object load( + ResourceFactory rf, + String srcResourceName, + Object srcObj, + String resourceName, + Field field, + Object attachment) { + try { + if ((srcObj instanceof Service) && Sncp.isRemote((Service) srcObj)) { + return null; // 远程模式不得注入 + } + ResourceFactory resourceFactory = engine.getResourceFactory(); + Class mapperType = (Class) field.getType(); + DataSqlMapper old = resourceFactory.find(resourceName, mapperType); + if (old != null) { + return old; + } + DataSource source = engine.loadDataSource(resourceName, false); + DataSqlMapper mapper = + DataSqlMapperBuilder.createMapper(engine.nativeSqlParser, (DataSqlSource) source, mapperType); + resourceFactory.register(resourceName, mapperType, mapper); + if (field != null) { + field.set(srcObj, mapper); + } + return mapper; + } catch (Exception e) { + logger.log(Level.SEVERE, DataSqlMapper.class.getSimpleName() + " inject to " + srcObj + " error", e); + throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); + } + } + + @Override + public Type resourceType() { + return DataSqlMapper.class; + } +} diff --git a/src/main/java/org/redkale/source/spi/SourceModuleEngine.java b/src/main/java/org/redkale/source/spi/SourceModuleEngine.java index a91413ae9..bd035564c 100644 --- a/src/main/java/org/redkale/source/spi/SourceModuleEngine.java +++ b/src/main/java/org/redkale/source/spi/SourceModuleEngine.java @@ -3,8 +3,6 @@ */ package org.redkale.source.spi; -import java.lang.reflect.Field; -import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -19,14 +17,10 @@ import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; -import org.redkale.annotation.Resource; import org.redkale.boot.Application; import org.redkale.boot.ModuleEngine; import org.redkale.inject.Resourcable; import org.redkale.inject.ResourceEvent; -import org.redkale.inject.ResourceFactory; -import org.redkale.inject.ResourceTypeLoader; -import org.redkale.net.Servlet; import org.redkale.net.sncp.Sncp; import org.redkale.service.Service; import org.redkale.source.AbstractCacheSource; @@ -38,7 +32,6 @@ import org.redkale.source.DataMemorySource; import org.redkale.source.DataNativeSqlParser; import org.redkale.source.DataSource; import org.redkale.source.DataSources; -import org.redkale.source.DataSqlMapper; import org.redkale.source.DataSqlSource; import org.redkale.source.SearchSource; import org.redkale.source.SourceManager; @@ -46,7 +39,6 @@ import org.redkale.util.AnyValue; import org.redkale.util.AnyValueWriter; import org.redkale.util.InstanceProvider; import org.redkale.util.RedkaleClassLoader; -import org.redkale.util.RedkaleException; import org.redkale.util.Utility; /** @author zhangjx */ @@ -135,9 +127,9 @@ public class SourceModuleEngine extends ModuleEngine implements SourceManager { } resourceFactory.register(SourceManager.class, this); // --------------------------------- 注册 DataSource、CacheSource --------------------------------- - resourceFactory.register(new DataSourceLoader()); - resourceFactory.register(new CacheSourceLoader()); - resourceFactory.register(new DataSqlMapperLoader()); + resourceFactory.register(new DataSourceLoader(this)); + resourceFactory.register(new CacheSourceLoader(this)); + resourceFactory.register(new DataSqlMapperLoader(this)); } /** @@ -545,115 +537,4 @@ public class SourceModuleEngine extends ModuleEngine implements SourceManager { return conf; } - private class DataSqlMapperLoader implements ResourceTypeLoader { - - @Override - public Object load( - ResourceFactory rf, - String srcResourceName, - Object srcObj, - String resourceName, - Field field, - Object attachment) { - try { - if ((srcObj instanceof Service) && Sncp.isRemote((Service) srcObj)) { - return null; // 远程模式不得注入 - } - Class mapperType = (Class) field.getType(); - DataSqlMapper old = resourceFactory.find(resourceName, mapperType); - if (old != null) { - return old; - } - DataSource source = loadDataSource(resourceName, false); - DataSqlMapper mapper = - DataSqlMapperBuilder.createMapper(nativeSqlParser, (DataSqlSource) source, mapperType); - resourceFactory.register(resourceName, mapperType, mapper); - field.set(srcObj, mapper); - return mapper; - } catch (Exception e) { - logger.log(Level.SEVERE, DataSqlMapper.class.getSimpleName() + " inject to " + srcObj + " error", e); - throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); - } - } - - @Override - public Type resourceType() { - return DataSqlMapper.class; - } - } - - private class DataSourceLoader implements ResourceTypeLoader { - - @Override - public Object load( - ResourceFactory rf, - String srcResourceName, - Object srcObj, - String resourceName, - Field field, - Object attachment) { - try { - if ((srcObj instanceof Service) && Sncp.isRemote((Service) srcObj)) { - return null; // 远程模式不得注入 - } - DataSource source = loadDataSource(resourceName, false); - field.set(srcObj, source); - return source; - } catch (Exception e) { - logger.log(Level.SEVERE, "DataSource inject to " + srcObj + " error", e); - throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); - } - } - - @Override - public Type resourceType() { - return DataSource.class; - } - } - - private class CacheSourceLoader implements ResourceTypeLoader { - - @Override - public Object load( - ResourceFactory rf, - String srcResourceName, - Object srcObj, - String resourceName, - Field field, - Object attachment) { - try { - if ((srcObj instanceof Service) && Sncp.isRemote((Service) srcObj)) { - return null; // 远程模式不得注入 - } - if (srcObj instanceof Servlet) { - throw new RedkaleException("CacheSource cannot inject in Servlet " + srcObj); - } - final boolean ws = (srcObj instanceof org.redkale.net.http.WebSocketNodeService); - CacheSource source = loadCacheSource(resourceName, ws); - field.set(srcObj, source); - Resource res = field.getAnnotation(Resource.class); - if (res != null && res.required() && source == null) { - throw new RedkaleException("CacheSource (resourceName = '" + resourceName + "') not found"); - } else { - logger.info("Load CacheSource (type = " - + (source == null ? null : source.getClass().getSimpleName()) + ", resourceName = '" - + resourceName + "')"); - } - return source; - } catch (Exception e) { - logger.log(Level.SEVERE, "DataSource inject error", e); - throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e); - } - } - - @Override - public Type resourceType() { - return CacheSource.class; - } - - @Override - public boolean autoNone() { - return false; - } - } }