调整ResourceTypeLoader
This commit is contained in:
@@ -391,7 +391,9 @@ public final class Application {
|
|||||||
Field field,
|
Field field,
|
||||||
Object attachment) {
|
Object attachment) {
|
||||||
try {
|
try {
|
||||||
|
if (field != null) {
|
||||||
field.set(srcObj, application);
|
field.set(srcObj, application);
|
||||||
|
}
|
||||||
return application;
|
return application;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, "Resource inject error", e);
|
logger.log(Level.SEVERE, "Resource inject error", e);
|
||||||
@@ -423,7 +425,9 @@ public final class Application {
|
|||||||
boolean serv =
|
boolean serv =
|
||||||
RESNAME_SERVER_RESFACTORY.equals(resourceName) || resourceName.equalsIgnoreCase("server");
|
RESNAME_SERVER_RESFACTORY.equals(resourceName) || resourceName.equalsIgnoreCase("server");
|
||||||
ResourceFactory rs = serv ? rf : (resourceName.isEmpty() ? application.resourceFactory : null);
|
ResourceFactory rs = serv ? rf : (resourceName.isEmpty() ? application.resourceFactory : null);
|
||||||
|
if (field != null) {
|
||||||
field.set(srcObj, rs);
|
field.set(srcObj, rs);
|
||||||
|
}
|
||||||
return rs;
|
return rs;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, "Resource inject error", e);
|
logger.log(Level.SEVERE, "Resource inject error", e);
|
||||||
@@ -462,7 +466,9 @@ public final class Application {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (field != null) {
|
||||||
field.set(srcObj, server);
|
field.set(srcObj, server);
|
||||||
|
}
|
||||||
return server;
|
return server;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, "Resource inject error", e);
|
logger.log(Level.SEVERE, "Resource inject error", e);
|
||||||
@@ -501,7 +507,9 @@ public final class Application {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (field != null) {
|
||||||
field.set(srcObj, server);
|
field.set(srcObj, server);
|
||||||
|
}
|
||||||
return server;
|
return server;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, "Resource inject error", e);
|
logger.log(Level.SEVERE, "Resource inject error", e);
|
||||||
@@ -540,7 +548,9 @@ public final class Application {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (field != null) {
|
||||||
field.set(srcObj, server);
|
field.set(srcObj, server);
|
||||||
|
}
|
||||||
return server;
|
return server;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, "Resource inject error", e);
|
logger.log(Level.SEVERE, "Resource inject error", e);
|
||||||
@@ -578,7 +588,9 @@ public final class Application {
|
|||||||
builder.version(HttpClient.Version.HTTP_2);
|
builder.version(HttpClient.Version.HTTP_2);
|
||||||
}
|
}
|
||||||
java.net.http.HttpClient httpClient = builder.build();
|
java.net.http.HttpClient httpClient = builder.build();
|
||||||
|
if (field != null) {
|
||||||
field.set(srcObj, httpClient);
|
field.set(srcObj, httpClient);
|
||||||
|
}
|
||||||
rf.inject(resourceName, httpClient, null); // 给其可能包含@Resource的字段赋值;
|
rf.inject(resourceName, httpClient, null); // 给其可能包含@Resource的字段赋值;
|
||||||
rf.register(resourceName, java.net.http.HttpClient.class, httpClient);
|
rf.register(resourceName, java.net.http.HttpClient.class, httpClient);
|
||||||
return httpClient;
|
return httpClient;
|
||||||
@@ -606,7 +618,9 @@ public final class Application {
|
|||||||
Object attachment) {
|
Object attachment) {
|
||||||
try {
|
try {
|
||||||
WebClient httpClient = WebClient.create(workExecutor, clientAsyncGroup);
|
WebClient httpClient = WebClient.create(workExecutor, clientAsyncGroup);
|
||||||
|
if (field != null) {
|
||||||
field.set(srcObj, httpClient);
|
field.set(srcObj, httpClient);
|
||||||
|
}
|
||||||
rf.inject(resourceName, httpClient, null); // 给其可能包含@Resource的字段赋值;
|
rf.inject(resourceName, httpClient, null); // 给其可能包含@Resource的字段赋值;
|
||||||
rf.register(resourceName, WebClient.class, httpClient);
|
rf.register(resourceName, WebClient.class, httpClient);
|
||||||
return httpClient;
|
return httpClient;
|
||||||
@@ -640,7 +654,9 @@ public final class Application {
|
|||||||
|| !Objects.equals(clusterAgent.getName(), resourceName)
|
|| !Objects.equals(clusterAgent.getName(), resourceName)
|
||||||
|| messageAgent.isRpcFirst()) {
|
|| messageAgent.isRpcFirst()) {
|
||||||
HttpRpcClient rpcClient = messageAgent.getHttpRpcClient();
|
HttpRpcClient rpcClient = messageAgent.getHttpRpcClient();
|
||||||
|
if (field != null) {
|
||||||
field.set(srcObj, rpcClient);
|
field.set(srcObj, rpcClient);
|
||||||
|
}
|
||||||
rf.inject(resourceName, rpcClient, null); // 给其可能包含@Resource的字段赋值;
|
rf.inject(resourceName, rpcClient, null); // 给其可能包含@Resource的字段赋值;
|
||||||
rf.register(resourceName, HttpRpcClient.class, rpcClient);
|
rf.register(resourceName, HttpRpcClient.class, rpcClient);
|
||||||
return rpcClient;
|
return rpcClient;
|
||||||
@@ -648,13 +664,17 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
if (clusterAgent == null) {
|
if (clusterAgent == null) {
|
||||||
HttpRpcClient rpcClient = new HttpLocalRpcClient(application, resourceName);
|
HttpRpcClient rpcClient = new HttpLocalRpcClient(application, resourceName);
|
||||||
|
if (field != null) {
|
||||||
field.set(srcObj, rpcClient);
|
field.set(srcObj, rpcClient);
|
||||||
|
}
|
||||||
rf.inject(resourceName, rpcClient, null); // 给其可能包含@Resource的字段赋值;
|
rf.inject(resourceName, rpcClient, null); // 给其可能包含@Resource的字段赋值;
|
||||||
rf.register(resourceName, HttpRpcClient.class, rpcClient);
|
rf.register(resourceName, HttpRpcClient.class, rpcClient);
|
||||||
return rpcClient;
|
return rpcClient;
|
||||||
}
|
}
|
||||||
HttpRpcClient rpcClient = new HttpClusterRpcClient(application, resourceName, clusterAgent);
|
HttpRpcClient rpcClient = new HttpClusterRpcClient(application, resourceName, clusterAgent);
|
||||||
|
if (field != null) {
|
||||||
field.set(srcObj, rpcClient);
|
field.set(srcObj, rpcClient);
|
||||||
|
}
|
||||||
rf.inject(resourceName, rpcClient, null); // 给其可能包含@Resource的字段赋值;
|
rf.inject(resourceName, rpcClient, null); // 给其可能包含@Resource的字段赋值;
|
||||||
rf.register(resourceName, HttpRpcClient.class, rpcClient);
|
rf.register(resourceName, HttpRpcClient.class, rpcClient);
|
||||||
return rpcClient;
|
return rpcClient;
|
||||||
|
|||||||
@@ -38,6 +38,18 @@ public abstract class ModuleEngine {
|
|||||||
this.environment = Objects.requireNonNull(application.getEnvironment());
|
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表示模块不识别此配置项
|
* 判断模块的配置项合并策略, 返回null表示模块不识别此配置项
|
||||||
*
|
*
|
||||||
|
|||||||
123
src/main/java/org/redkale/boot/NodeAutoServiceLoader.java
Normal file
123
src/main/java/org/redkale/boot/NodeAutoServiceLoader.java
Normal file
@@ -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<Service> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
162
src/main/java/org/redkale/boot/NodeExpectServiceLoader.java
Normal file
162
src/main/java/org/redkale/boot/NodeExpectServiceLoader.java
Normal file
@@ -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<? extends Service> serviceImplClass;
|
||||||
|
|
||||||
|
private final AtomicInteger serviceCount;
|
||||||
|
|
||||||
|
private final SncpRpcGroups rpcGroups;
|
||||||
|
|
||||||
|
private final ClassFilter.FilterEntry<? extends Service> entry;
|
||||||
|
|
||||||
|
private final String group;
|
||||||
|
|
||||||
|
private final boolean localMode;
|
||||||
|
|
||||||
|
public NodeExpectServiceLoader(
|
||||||
|
NodeServer nodeServer,
|
||||||
|
Class type,
|
||||||
|
Class<? extends Service> serviceImplClass,
|
||||||
|
AtomicInteger serviceCount,
|
||||||
|
SncpRpcGroups rpcGroups,
|
||||||
|
ClassFilter.FilterEntry<? extends Service> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,8 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.boot;
|
package org.redkale.boot;
|
||||||
|
|
||||||
import static org.redkale.boot.Application.RESNAME_SNCP_ADDRESS;
|
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
@@ -16,11 +14,8 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.redkale.annotation.*;
|
import org.redkale.annotation.*;
|
||||||
import org.redkale.asm.AsmMethodBoost;
|
|
||||||
import org.redkale.boot.ClassFilter.FilterEntry;
|
import org.redkale.boot.ClassFilter.FilterEntry;
|
||||||
import org.redkale.cluster.spi.ClusterAgent;
|
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.mq.spi.MessageAgent;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
import org.redkale.net.http.*;
|
import org.redkale.net.http.*;
|
||||||
@@ -124,7 +119,7 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
@Override
|
@Override
|
||||||
protected void loadService(ClassFilter<? extends Service> serviceFilter) throws Exception {
|
protected void loadService(ClassFilter<? extends Service> serviceFilter) throws Exception {
|
||||||
super.loadService(serviceFilter);
|
super.loadService(serviceFilter);
|
||||||
initWebSocketService();
|
resourceFactory.register(new NodeWebSocketNodeLoader(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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")
|
@SuppressWarnings("unchecked")
|
||||||
protected void loadHttpFilter(final ClassFilter<? extends Filter> classFilter) throws Exception {
|
protected void loadHttpFilter(final ClassFilter<? extends Filter> classFilter) throws Exception {
|
||||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.boot;
|
package org.redkale.boot;
|
||||||
|
|
||||||
import static org.redkale.boot.Application.*;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
@@ -18,19 +16,15 @@ import java.util.concurrent.CountDownLatch;
|
|||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.logging.*;
|
import java.util.logging.*;
|
||||||
import org.redkale.annotation.*;
|
import org.redkale.annotation.*;
|
||||||
import org.redkale.annotation.AutoLoad;
|
|
||||||
import org.redkale.annotation.Command;
|
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.boot.ClassFilter.FilterEntry;
|
||||||
import org.redkale.cluster.spi.ClusterAgent;
|
import org.redkale.cluster.spi.ClusterAgent;
|
||||||
import org.redkale.inject.ResourceFactory;
|
import org.redkale.inject.ResourceFactory;
|
||||||
import org.redkale.inject.ResourceTypeLoader;
|
|
||||||
import org.redkale.mq.spi.MessageAgent;
|
import org.redkale.mq.spi.MessageAgent;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
import org.redkale.net.Filter;
|
import org.redkale.net.Filter;
|
||||||
import org.redkale.net.client.ClientAddress;
|
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.net.sncp.*;
|
||||||
import org.redkale.service.*;
|
import org.redkale.service.*;
|
||||||
import org.redkale.source.*;
|
import org.redkale.source.*;
|
||||||
@@ -202,7 +196,12 @@ public abstract class NodeServer {
|
|||||||
1000);
|
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", "");
|
String interceptorClass = this.serverConf.getValue("interceptor", "");
|
||||||
if (!interceptorClass.isEmpty()) {
|
if (!interceptorClass.isEmpty()) {
|
||||||
Class clazz = serverClassLoader.loadClass(interceptorClass);
|
Class clazz = serverClassLoader.loadClass(interceptorClass);
|
||||||
@@ -265,305 +264,6 @@ public abstract class NodeServer {
|
|||||||
|
|
||||||
protected abstract void loadServlet(ClassFilter<? extends Servlet> servletFilter) throws Exception;
|
protected abstract void loadServlet(ClassFilter<? extends Servlet> 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<String> 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<Service> 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<? extends Service> serviceImplClass;
|
|
||||||
|
|
||||||
private final AtomicInteger serviceCount;
|
|
||||||
|
|
||||||
private final SncpRpcGroups rpcGroups;
|
|
||||||
|
|
||||||
private final FilterEntry<? extends Service> entry;
|
|
||||||
|
|
||||||
private final String group;
|
|
||||||
|
|
||||||
private final boolean localMode;
|
|
||||||
|
|
||||||
public ExpectServiceLoader(
|
|
||||||
Class type,
|
|
||||||
Class<? extends Service> serviceImplClass,
|
|
||||||
AtomicInteger serviceCount,
|
|
||||||
SncpRpcGroups rpcGroups,
|
|
||||||
FilterEntry<? extends Service> 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")
|
@SuppressWarnings("unchecked")
|
||||||
protected void loadService(ClassFilter<? extends Service> serviceFilter) throws Exception {
|
protected void loadService(ClassFilter<? extends Service> serviceFilter) throws Exception {
|
||||||
Objects.requireNonNull(serviceFilter);
|
Objects.requireNonNull(serviceFilter);
|
||||||
@@ -618,12 +318,12 @@ public abstract class NodeServer {
|
|||||||
if (entry.isExpect()) {
|
if (entry.isExpect()) {
|
||||||
Class t = ResourceFactory.getResourceType(entry.getType());
|
Class t = ResourceFactory.getResourceType(entry.getType());
|
||||||
if (resourceFactory.findResourceTypeLoader(t) == null) {
|
if (resourceFactory.findResourceTypeLoader(t) == null) {
|
||||||
resourceFactory.register(new ExpectServiceLoader(
|
resourceFactory.register(new NodeExpectServiceLoader(
|
||||||
t, serviceImplClass, serviceCount, rpcGroups, entry, group, localMode));
|
this, t, serviceImplClass, serviceCount, rpcGroups, entry, group, localMode));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ExpectServiceLoader resourceLoader = new ExpectServiceLoader(
|
NodeExpectServiceLoader resourceLoader = new NodeExpectServiceLoader(
|
||||||
serviceImplClass, serviceImplClass, serviceCount, rpcGroups, entry, group, localMode);
|
this, serviceImplClass, serviceImplClass, serviceCount, rpcGroups, entry, group, localMode);
|
||||||
resourceLoader.load(resourceFactory, null, null, entry.getName(), null, false);
|
resourceLoader.load(resourceFactory, null, null, entry.getName(), null, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
206
src/main/java/org/redkale/boot/NodeWebSocketNodeLoader.java
Normal file
206
src/main/java/org/redkale/boot/NodeWebSocketNodeLoader.java
Normal file
@@ -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<String> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -92,7 +92,7 @@ public class CachedAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void init(ResourceFactory resourceFactory, Object service) {
|
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());
|
String key = environment.getPropertyValue(cached.getKey());
|
||||||
this.templetKey = key;
|
this.templetKey = key;
|
||||||
if (key.startsWith("@")) { // 动态加载缓存key生成器
|
if (key.startsWith("@")) { // 动态加载缓存key生成器
|
||||||
|
|||||||
@@ -233,6 +233,7 @@ public class CachedAsmMethodBoost extends AsmMethodBoost {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionMap.forEach((field, action) -> {
|
actionMap.forEach((field, action) -> {
|
||||||
try {
|
try {
|
||||||
resourceFactory.inject(action);
|
resourceFactory.inject(action);
|
||||||
|
|||||||
@@ -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<String, CachedKeyGenerator> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<String, AnyValue> configMap;
|
||||||
|
|
||||||
|
public CachedManagerLoader(CachedModuleEngine engine, Map<String, AnyValue> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -117,16 +117,16 @@ public class CachedManagerService implements CachedManager, Service {
|
|||||||
this.schema = conf.getValue("schema", DEFAULT_SCHEMA);
|
this.schema = conf.getValue("schema", DEFAULT_SCHEMA);
|
||||||
if (this.enabled) {
|
if (this.enabled) {
|
||||||
this.localSource.init(conf);
|
this.localSource.init(conf);
|
||||||
String remoteSourceName = conf.getValue("remote");
|
String remoteSourceName = conf.getValue("remote", "");
|
||||||
if (remoteSource == null && remoteSourceName != null) {
|
if (remoteSource == null && remoteSourceName != null) {
|
||||||
this.broadcastable = conf.getBoolValue("broadcastable", true);
|
|
||||||
CacheSource source = application.loadCacheSource(remoteSourceName, false);
|
CacheSource source = application.loadCacheSource(remoteSourceName, false);
|
||||||
if (source == null) {
|
if (source == null && !remoteSourceName.isEmpty()) {
|
||||||
throw new RedkaleException("Not found CacheSource '" + remoteSourceName + "'");
|
throw new RedkaleException("Not found CacheSource '" + remoteSourceName + "'");
|
||||||
}
|
}
|
||||||
this.remoteSource = source;
|
this.remoteSource = source;
|
||||||
|
this.broadcastable = conf.getBoolValue("broadcastable", true);
|
||||||
}
|
}
|
||||||
if (remoteSource != null) {
|
if (remoteSource != null && this.broadcastable) {
|
||||||
this.remoteListener = new CacheRemoteListener();
|
this.remoteListener = new CacheRemoteListener();
|
||||||
this.remoteSource.subscribe(CachedEventMessage.class, remoteListener, getChannelTopic());
|
this.remoteSource.subscribe(CachedEventMessage.class, remoteListener, getChannelTopic());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,26 +3,19 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.cached.spi;
|
package org.redkale.cached.spi;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Level;
|
|
||||||
import org.redkale.asm.AsmMethodBoost;
|
import org.redkale.asm.AsmMethodBoost;
|
||||||
import org.redkale.boot.Application;
|
import org.redkale.boot.Application;
|
||||||
import org.redkale.boot.ModuleEngine;
|
import org.redkale.boot.ModuleEngine;
|
||||||
import org.redkale.cached.CachedManager;
|
import org.redkale.cached.CachedManager;
|
||||||
import org.redkale.inject.ResourceFactory;
|
|
||||||
import org.redkale.inject.ResourceTypeLoader;
|
|
||||||
import org.redkale.service.Service;
|
import org.redkale.service.Service;
|
||||||
import org.redkale.util.AnyValue;
|
import org.redkale.util.AnyValue;
|
||||||
import org.redkale.util.AnyValueWriter;
|
|
||||||
import org.redkale.util.InstanceProvider;
|
import org.redkale.util.InstanceProvider;
|
||||||
import org.redkale.util.RedkaleClassLoader;
|
import org.redkale.util.RedkaleClassLoader;
|
||||||
import org.redkale.util.RedkaleException;
|
import org.redkale.util.RedkaleException;
|
||||||
@@ -40,7 +33,7 @@ public class CachedModuleEngine extends ModuleEngine {
|
|||||||
protected static final String CONFIG_NAME = "cached";
|
protected static final String CONFIG_NAME = "cached";
|
||||||
|
|
||||||
// 全局缓存管理器
|
// 全局缓存管理器
|
||||||
private ConcurrentHashMap<String, ManagerEntity> cacheManagerMap = new ConcurrentHashMap<>();
|
protected ConcurrentHashMap<String, ManagerEntity> cacheManagerMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public CachedModuleEngine(Application application) {
|
public CachedModuleEngine(Application application) {
|
||||||
super(application);
|
super(application);
|
||||||
@@ -81,7 +74,7 @@ public class CachedModuleEngine extends ModuleEngine {
|
|||||||
// 设置缓存管理器
|
// 设置缓存管理器
|
||||||
AnyValue[] configs = application.getAppConfig().getAnyValues(CONFIG_NAME);
|
AnyValue[] configs = application.getAppConfig().getAnyValues(CONFIG_NAME);
|
||||||
if (configs == null || configs.length == 0) {
|
if (configs == null || configs.length == 0) {
|
||||||
configs = new AnyValue[] {new AnyValueWriter()};
|
configs = new AnyValue[] {AnyValue.create()};
|
||||||
}
|
}
|
||||||
Map<String, AnyValue> configMap = new HashMap<>();
|
Map<String, AnyValue> configMap = new HashMap<>();
|
||||||
for (AnyValue config : configs) {
|
for (AnyValue config : configs) {
|
||||||
@@ -92,94 +85,8 @@ public class CachedModuleEngine extends ModuleEngine {
|
|||||||
}
|
}
|
||||||
configMap.put(name, config);
|
configMap.put(name, config);
|
||||||
}
|
}
|
||||||
this.resourceFactory.register(new ResourceTypeLoader() {
|
this.resourceFactory.register(new CachedManagerLoader(this, configMap));
|
||||||
|
this.resourceFactory.register(new CachedKeyGeneratorLoader(this));
|
||||||
@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<String, CachedKeyGenerator> 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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -198,7 +105,7 @@ public class CachedModuleEngine extends ModuleEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private CachedManager createManager(AnyValue conf) {
|
protected CachedManager createManager(AnyValue conf) {
|
||||||
Iterator<CachedManagerProvider> it = ServiceLoader.load(
|
Iterator<CachedManagerProvider> it = ServiceLoader.load(
|
||||||
CachedManagerProvider.class, application.getClassLoader())
|
CachedManagerProvider.class, application.getClassLoader())
|
||||||
.iterator();
|
.iterator();
|
||||||
|
|||||||
@@ -686,6 +686,32 @@ public final class ResourceFactory {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <A> A load(Class<? extends A> clazz) {
|
||||||
|
return load("", clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <A> 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> A load(String name, Class<? extends A> 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> List<A> query(Class<? extends A> clazz) {
|
public <A> List<A> query(Class<? extends A> clazz) {
|
||||||
return query(new ArrayList<>(), clazz);
|
return query(new ArrayList<>(), clazz);
|
||||||
}
|
}
|
||||||
@@ -1097,7 +1123,7 @@ public final class ResourceFactory {
|
|||||||
return parent == null ? null : parent.findResourceTypeLoader(clazz);
|
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);
|
ResourceTypeLoader it = this.findMatchTypeLoader(ft, field);
|
||||||
return it == null ? findRegxTypeLoader(ft, field) : it;
|
return it == null ? findRegxTypeLoader(ft, field) : it;
|
||||||
}
|
}
|
||||||
@@ -1109,7 +1135,7 @@ public final class ResourceFactory {
|
|||||||
return parent.parentRoot();
|
return parent.parentRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResourceTypeLoader findMatchTypeLoader(Type ft, Field field) {
|
private ResourceTypeLoader findMatchTypeLoader(Type ft, @Nullable Field field) {
|
||||||
ResourceTypeLoader it = this.resTypeLoaderMap.get(ft);
|
ResourceTypeLoader it = this.resTypeLoaderMap.get(ft);
|
||||||
if (it == null && field != null) {
|
if (it == null && field != null) {
|
||||||
it = this.resTypeLoaderMap.get(field.getType());
|
it = this.resTypeLoaderMap.get(field.getType());
|
||||||
@@ -1120,7 +1146,7 @@ public final class ResourceFactory {
|
|||||||
return parent == null ? null : parent.findMatchTypeLoader(ft, field);
|
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) {
|
if (field == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package org.redkale.inject;
|
|||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import org.redkale.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义注入加载器
|
* 自定义注入加载器
|
||||||
@@ -14,18 +15,38 @@ import java.lang.reflect.Type;
|
|||||||
*/
|
*/
|
||||||
public interface ResourceTypeLoader {
|
public interface ResourceTypeLoader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义的对象注入, 实现需要兼容Field为null的情况
|
||||||
|
*
|
||||||
|
* @param factory ResourceFactory
|
||||||
|
* @param srcResourceName 依附对象的资源名
|
||||||
|
* @param srcObj 依附对象
|
||||||
|
* @param resourceName 资源名
|
||||||
|
* @param field 字段对象
|
||||||
|
* @param attachment
|
||||||
|
* @return Object
|
||||||
|
*/
|
||||||
public Object load(
|
public Object load(
|
||||||
ResourceFactory factory,
|
ResourceFactory factory,
|
||||||
String srcResourceName,
|
@Nullable String srcResourceName,
|
||||||
Object srcObj,
|
@Nullable Object srcObj,
|
||||||
String resourceName,
|
String resourceName,
|
||||||
Field field,
|
@Nullable Field field,
|
||||||
Object attachment);
|
@Nullable Object attachment);
|
||||||
|
/**
|
||||||
|
* 注入加载器对应的类型
|
||||||
|
*
|
||||||
|
* @return 类型
|
||||||
|
*/
|
||||||
public Type resourceType();
|
public Type resourceType();
|
||||||
|
|
||||||
// 返回true: 表示调用ResourceLoader之后资源仍不存在,则会在ResourceFactory里注入默认值null。
|
/**
|
||||||
// 返回false: 表示资源不存在下次仍会调用ResourceLoader自行处理。
|
* 是否注入默认值null <br>
|
||||||
|
* 返回true: 表示调用ResourceLoader之后资源仍不存在,则会在ResourceFactory里注入默认值null。 <br>
|
||||||
|
* 返回false: 表示资源不存在下次仍会调用{@link org.redkale.inject.ResourceTypeLoader}自行处理。 <br>
|
||||||
|
*
|
||||||
|
* @return 是否注入默认值null
|
||||||
|
*/
|
||||||
default boolean autoNone() {
|
default boolean autoNone() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
78
src/main/java/org/redkale/source/spi/CacheSourceLoader.java
Normal file
78
src/main/java/org/redkale/source/spi/CacheSourceLoader.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
59
src/main/java/org/redkale/source/spi/DataSourceLoader.java
Normal file
59
src/main/java/org/redkale/source/spi/DataSourceLoader.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<? extends DataSqlMapper> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,8 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.source.spi;
|
package org.redkale.source.spi;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -19,14 +17,10 @@ import java.util.Set;
|
|||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.redkale.annotation.Resource;
|
|
||||||
import org.redkale.boot.Application;
|
import org.redkale.boot.Application;
|
||||||
import org.redkale.boot.ModuleEngine;
|
import org.redkale.boot.ModuleEngine;
|
||||||
import org.redkale.inject.Resourcable;
|
import org.redkale.inject.Resourcable;
|
||||||
import org.redkale.inject.ResourceEvent;
|
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.net.sncp.Sncp;
|
||||||
import org.redkale.service.Service;
|
import org.redkale.service.Service;
|
||||||
import org.redkale.source.AbstractCacheSource;
|
import org.redkale.source.AbstractCacheSource;
|
||||||
@@ -38,7 +32,6 @@ import org.redkale.source.DataMemorySource;
|
|||||||
import org.redkale.source.DataNativeSqlParser;
|
import org.redkale.source.DataNativeSqlParser;
|
||||||
import org.redkale.source.DataSource;
|
import org.redkale.source.DataSource;
|
||||||
import org.redkale.source.DataSources;
|
import org.redkale.source.DataSources;
|
||||||
import org.redkale.source.DataSqlMapper;
|
|
||||||
import org.redkale.source.DataSqlSource;
|
import org.redkale.source.DataSqlSource;
|
||||||
import org.redkale.source.SearchSource;
|
import org.redkale.source.SearchSource;
|
||||||
import org.redkale.source.SourceManager;
|
import org.redkale.source.SourceManager;
|
||||||
@@ -46,7 +39,6 @@ import org.redkale.util.AnyValue;
|
|||||||
import org.redkale.util.AnyValueWriter;
|
import org.redkale.util.AnyValueWriter;
|
||||||
import org.redkale.util.InstanceProvider;
|
import org.redkale.util.InstanceProvider;
|
||||||
import org.redkale.util.RedkaleClassLoader;
|
import org.redkale.util.RedkaleClassLoader;
|
||||||
import org.redkale.util.RedkaleException;
|
|
||||||
import org.redkale.util.Utility;
|
import org.redkale.util.Utility;
|
||||||
|
|
||||||
/** @author zhangjx */
|
/** @author zhangjx */
|
||||||
@@ -135,9 +127,9 @@ public class SourceModuleEngine extends ModuleEngine implements SourceManager {
|
|||||||
}
|
}
|
||||||
resourceFactory.register(SourceManager.class, this);
|
resourceFactory.register(SourceManager.class, this);
|
||||||
// --------------------------------- 注册 DataSource、CacheSource ---------------------------------
|
// --------------------------------- 注册 DataSource、CacheSource ---------------------------------
|
||||||
resourceFactory.register(new DataSourceLoader());
|
resourceFactory.register(new DataSourceLoader(this));
|
||||||
resourceFactory.register(new CacheSourceLoader());
|
resourceFactory.register(new CacheSourceLoader(this));
|
||||||
resourceFactory.register(new DataSqlMapperLoader());
|
resourceFactory.register(new DataSqlMapperLoader(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -545,115 +537,4 @@ public class SourceModuleEngine extends ModuleEngine implements SourceManager {
|
|||||||
return conf;
|
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<? extends DataSqlMapper> 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user