From 511a31bf9531d37d195504c9df8637c8abfdf80e Mon Sep 17 00:00:00 2001
From: RedKale <22250530@qq.com>
Date: Sun, 26 Jun 2016 14:08:35 +0800
Subject: [PATCH]
---
src/org/redkale/boot/ClassFilter.java | 68 ++++++++++++----
src/org/redkale/boot/NodeServer.java | 82 ++++++++++++++------
src/org/redkale/net/sncp/ServiceWrapper.java | 5 ++
src/org/redkale/util/AutoLoad.java | 2 +-
src/org/redkale/util/ResourceFactory.java | 14 +++-
5 files changed, 129 insertions(+), 42 deletions(-)
diff --git a/src/org/redkale/boot/ClassFilter.java b/src/org/redkale/boot/ClassFilter.java
index 53c5aefd5..085be5466 100644
--- a/src/org/redkale/boot/ClassFilter.java
+++ b/src/org/redkale/boot/ClassFilter.java
@@ -14,13 +14,12 @@ import java.util.concurrent.*;
import java.util.jar.*;
import java.util.logging.*;
import java.util.regex.*;
-import org.redkale.util.AnyValue;
+import org.redkale.util.*;
import org.redkale.util.AnyValue.DefaultAnyValue;
-import org.redkale.util.AutoLoad;
/**
* class过滤器, 符合条件的class会保留下来存入FilterEntry。
- *
+ *
*
* 详情见: http://redkale.org
*
@@ -30,8 +29,14 @@ import org.redkale.util.AutoLoad;
@SuppressWarnings("unchecked")
public final class ClassFilter {
+ private static final Logger logger = Logger.getLogger(ClassFilter.class.getName());
+
+ private static final boolean finer = logger.isLoggable(Level.FINER);
+
private final Set> entrys = new HashSet<>();
+ private final Set> expectEntrys = new HashSet<>();
+
private boolean refused;
private Class superClass;
@@ -79,10 +84,31 @@ public final class ClassFilter {
return entrys;
}
+ /**
+ * 获取预留的class集合
+ *
+ * @return Set<FilterEntry<T>>
+ */
+ public final Set> getFilterExpectEntrys() {
+ return expectEntrys;
+ }
+
+ /**
+ * 获取所有的class集合
+ *
+ * @return Set<FilterEntry<T>>
+ */
+ public final Set> getAllFilterEntrys() {
+ HashSet> rs = new HashSet<>();
+ rs.addAll(entrys);
+ rs.addAll(expectEntrys);
+ return rs;
+ }
+
/**
* 自动扫描地过滤指定的class
*
- * @param property AnyValue
+ * @param property AnyValue
* @param clazzname String
*/
@SuppressWarnings("unchecked")
@@ -93,9 +119,9 @@ public final class ClassFilter {
/**
* 过滤指定的class
*
- * @param property application.xml中对应class节点下的property属性项
+ * @param property application.xml中对应class节点下的property属性项
* @param clazzname class名称
- * @param autoscan 为true表示自动扫描的, false表示显著调用filter, AutoLoad的注解将被忽略
+ * @param autoscan 为true表示自动扫描的, false表示显著调用filter, AutoLoad的注解将被忽略
*/
public final void filter(AnyValue property, String clazzname, boolean autoscan) {
boolean r = accept0(property, clazzname);
@@ -129,8 +155,15 @@ public final class ClassFilter {
property = dav;
}
}
- entrys.add(new FilterEntry(clazz, autoscan, property));
+
+ AutoLoad auto = (AutoLoad) clazz.getAnnotation(AutoLoad.class);
+ if (autoscan && auto != null && !auto.value()) { //自动扫描且被标记为@AutoLoad(false)的
+ expectEntrys.add(new FilterEntry(clazz, autoscan, true, property));
+ } else {
+ entrys.add(new FilterEntry(clazz, autoscan, false, property));
+ }
} catch (Throwable cfe) {
+ if (finer) logger.log(Level.FINER, ClassFilter.class.getSimpleName() + " filter error", cfe);
}
}
@@ -152,8 +185,9 @@ public final class ClassFilter {
/**
* 判断class是否有效
*
- * @param property AnyValue
+ * @param property AnyValue
* @param classname String
+ *
* @return boolean
*/
public boolean accept(AnyValue property, String classname) {
@@ -191,17 +225,14 @@ public final class ClassFilter {
* 判断class是否有效
*
* @param property AnyValue
- * @param clazz Class
+ * @param clazz Class
* @param autoscan boolean
+ *
* @return boolean
*/
@SuppressWarnings("unchecked")
public boolean accept(AnyValue property, Class clazz, boolean autoscan) {
if (this.refused || !Modifier.isPublic(clazz.getModifiers())) return false;
- if (autoscan) {
- AutoLoad auto = (AutoLoad) clazz.getAnnotation(AutoLoad.class);
- if (auto != null && !auto.value()) return false;
- }
if (annotationClass != null && clazz.getAnnotation(annotationClass) == null) return false;
return superClass == null || (clazz != superClass && superClass.isAssignableFrom(clazz));
}
@@ -263,11 +294,13 @@ public final class ClassFilter {
private final boolean autoload;
+ private final boolean expect;
+
public FilterEntry(Class type, AnyValue property) {
- this(type, false, property);
+ this(type, false, false, property);
}
- public FilterEntry(Class type, final boolean autoload, AnyValue property) {
+ public FilterEntry(Class type, final boolean autoload, boolean expect, AnyValue property) {
this.type = type;
String str = property == null ? null : property.getValue("groups");
if (str != null) {
@@ -277,6 +310,7 @@ public final class ClassFilter {
if (str != null) groups.addAll(Arrays.asList(str.split(";")));
this.property = property;
this.autoload = autoload;
+ this.expect = expect;
this.name = property == null ? "" : property.getValue("name", "");
}
@@ -322,6 +356,9 @@ public final class ClassFilter {
return autoload;
}
+ public boolean isExpect() {
+ return expect;
+ }
}
/**
@@ -342,6 +379,7 @@ public final class ClassFilter {
*
* @param exclude 不需要扫描的文件夹, 可以为null
* @param filters 过滤器
+ *
* @throws IOException 异常
*/
public static void load(final File exclude, final ClassFilter... filters) throws IOException {
diff --git a/src/org/redkale/boot/NodeServer.java b/src/org/redkale/boot/NodeServer.java
index 28996edfb..5fc7a690b 100644
--- a/src/org/redkale/boot/NodeServer.java
+++ b/src/org/redkale/boot/NodeServer.java
@@ -21,6 +21,7 @@ import javax.persistence.Transient;
import static org.redkale.boot.Application.*;
import org.redkale.boot.ClassFilter.FilterEntry;
import org.redkale.net.*;
+import org.redkale.net.http.WebSocketNode;
import org.redkale.net.sncp.*;
import org.redkale.service.*;
import org.redkale.source.*;
@@ -249,13 +250,21 @@ public abstract class NodeServer {
protected void loadService(ClassFilter serviceFilter) throws Exception {
if (serviceFilter == null) return;
final String threadName = "[" + Thread.currentThread().getName() + "] ";
- final Set> entrys = serviceFilter.getFilterEntrys();
+ final Set> entrys = serviceFilter.getAllFilterEntrys();
ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : resourceFactory;
for (FilterEntry entry : entrys) { //service实现类
final Class extends Service> type = entry.getType();
if (Modifier.isFinal(type.getModifiers())) continue; //修饰final的类跳过
if (!Modifier.isPublic(type.getModifiers())) continue;
+ if (entry.isExpect()) {
+ if (Modifier.isAbstract(type.getModifiers())) continue; //修饰abstract的类跳过
+ if (DataSource.class.isAssignableFrom(type)) continue;
+ if (CacheSource.class.isAssignableFrom(type)) continue;
+ if (DataSQLListener.class.isAssignableFrom(type)) continue;
+ if (DataCacheListener.class.isAssignableFrom(type)) continue;
+ if (WebSocketNode.class.isAssignableFrom(type)) continue;
+ }
if (entry.getName().contains("$")) throw new RuntimeException(" value cannot contains '$' in " + entry.getProperty());
if (resourceFactory.find(entry.getName(), type) != null) continue; //Server加载Service时需要判断是否已经加载过了。
final HashSet groups = entry.getGroups(); //groups.isEmpty()表示没有配置groups属性。
@@ -266,29 +275,52 @@ public abstract class NodeServer {
|| (this.sncpGroup == null && entry.isEmptyGroups()) //空的SNCP配置
|| type.getAnnotation(LocalService.class) != null;//本地模式
if (localed && (type.isInterface() || Modifier.isAbstract(type.getModifiers()))) continue; //本地模式不能实例化接口和抽象类的Service类
-
- Service service;
- if (localed) { //本地模式
- service = Sncp.createLocalService(entry.getName(), getExecutor(), application.getResourceFactory(), type, this.sncpAddress, loadTransport(this.sncpGroup), loadTransports(groups));
- } else {
- service = Sncp.createRemoteService(entry.getName(), getExecutor(), type, this.sncpAddress, loadTransport(groups));
- }
- if (SncpClient.parseMethod(type).isEmpty()) continue; //class没有可用的方法, 通常为BaseService
- final ServiceWrapper wrapper = new ServiceWrapper(type, service, entry.getName(), localed ? this.sncpGroup : null, groups, entry.getProperty());
- for (final Class restype : wrapper.getTypes()) {
- if (resourceFactory.find(wrapper.getName(), restype) == null) {
- regFactory.register(wrapper.getName(), restype, wrapper.getService());
- } else if (isSNCP() && !entry.isAutoload()) {
- throw new RuntimeException(ServiceWrapper.class.getSimpleName() + "(class:" + type.getName() + ", name:" + entry.getName() + ", group:" + groups + ") is repeat.");
+ final Runnable runner = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Service service;
+ if (localed) { //本地模式
+ service = Sncp.createLocalService(entry.getName(), getExecutor(), application.getResourceFactory(), type,
+ NodeServer.this.sncpAddress, loadTransport(NodeServer.this.sncpGroup), loadTransports(groups));
+ } else {
+ service = Sncp.createRemoteService(entry.getName(), getExecutor(), type, NodeServer.this.sncpAddress, loadTransport(groups));
+ }
+ if (SncpClient.parseMethod(type).isEmpty()) return; //class没有可用的方法, 通常为BaseService
+ final ServiceWrapper wrapper = new ServiceWrapper(type, service, entry.getName(), localed ? NodeServer.this.sncpGroup : null, groups, entry.getProperty());
+ for (final Class restype : wrapper.getTypes()) {
+ if (resourceFactory.find(wrapper.getName(), restype) == null) {
+ regFactory.register(wrapper.getName(), restype, wrapper.getService());
+ } else if (isSNCP() && !entry.isAutoload()) {
+ throw new RuntimeException(ServiceWrapper.class.getSimpleName() + "(class:" + type.getName() + ", name:" + entry.getName() + ", group:" + groups + ") is repeat.");
+ }
+ }
+ if (wrapper.isRemote()) {
+ remoteServiceWrappers.add(wrapper);
+ } else {
+ localServiceWrappers.add(wrapper);
+ if (consumer != null) consumer.accept(wrapper);
+ }
+ } catch (RuntimeException ex) {
+ throw ex;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ if (entry.isExpect()) {
+ ResourceFactory.ResourceLoader resourceLoader = (ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) -> {
+ runner.run();
+ };
+ for (final Class restype : ServiceWrapper.parseTypes(entry.getType())) {
+ resourceFactory.register(resourceLoader, restype);
}
- }
- if (wrapper.isRemote()) {
- remoteServiceWrappers.add(wrapper);
} else {
- localServiceWrappers.add(wrapper);
- if (consumer != null) consumer.accept(wrapper);
+ runner.run();
}
+
}
+
application.servicecdl.countDown();
application.servicecdl.await();
@@ -297,12 +329,14 @@ public abstract class NodeServer {
new ArrayList<>(localServiceWrappers).forEach(y -> {
resourceFactory.inject(y.getService(), NodeServer.this);
});
- remoteServiceWrappers.forEach(y -> {
+ new ArrayList<>(remoteServiceWrappers).forEach(y -> {
resourceFactory.inject(y.getService(), NodeServer.this);
- if (sb != null) {
- sb.append(threadName).append(y.toSimpleString()).append(" loaded and injected").append(LINE_SEPARATOR);
- }
});
+ if (sb != null) {
+ remoteServiceWrappers.forEach(y -> {
+ sb.append(threadName).append(y.toSimpleString()).append(" loaded and injected").append(LINE_SEPARATOR);
+ });
+ }
//----------------- init -----------------
List swlist = new ArrayList<>(localServiceWrappers);
Collections.sort(swlist);
diff --git a/src/org/redkale/net/sncp/ServiceWrapper.java b/src/org/redkale/net/sncp/ServiceWrapper.java
index 744b02ccb..651640fd7 100644
--- a/src/org/redkale/net/sncp/ServiceWrapper.java
+++ b/src/org/redkale/net/sncp/ServiceWrapper.java
@@ -66,6 +66,11 @@ public final class ServiceWrapper implements Comparable servicetype) {
+ ResourceType rty = servicetype.getAnnotation(ResourceType.class);
+ return rty == null ? new Class[]{servicetype} : rty.value();
+ }
+
public String toSimpleString() {
StringBuilder sb = new StringBuilder();
sb.append(remote ? "RemoteService" : "LocalService ");
diff --git a/src/org/redkale/util/AutoLoad.java b/src/org/redkale/util/AutoLoad.java
index 65294f907..ff8298e8a 100644
--- a/src/org/redkale/util/AutoLoad.java
+++ b/src/org/redkale/util/AutoLoad.java
@@ -11,7 +11,7 @@ import java.lang.annotation.*;
/**
* 自动加载。 使用场景:
- * 1、被标记为@AutoLoad(false)的Service类不会被自动加载
+ * 1、被标记为@AutoLoad(false)的Service类不会被自动加载, 当被依赖时才会被加载
* 2、被标记为@AutoLoad(false)的Servlet类不会被自动加载
*
* 详情见: http://redkale.org
diff --git a/src/org/redkale/util/ResourceFactory.java b/src/org/redkale/util/ResourceFactory.java
index 93560e974..7a9ea0d09 100644
--- a/src/org/redkale/util/ResourceFactory.java
+++ b/src/org/redkale/util/ResourceFactory.java
@@ -373,16 +373,26 @@ public final class ResourceFactory {
}
}
- private ResourceLoader findLoader(Type ft, Field field) {
+ private ResourceLoader findMatchLoader(Type ft, Field field) {
ResourceLoader it = this.loadermap.get(ft);
+ if (it == null) it = this.loadermap.get(field.getType());
if (it != null) return it;
+ return parent == null ? null : parent.findMatchLoader(ft, field);
+ }
+
+ private ResourceLoader findRegxLoader(Type ft, Field field) {
Class c = field.getType();
for (Map.Entry en : this.loadermap.entrySet()) {
Type t = en.getKey();
if (t == ft) return en.getValue();
if (t instanceof Class && (((Class) t)).isAssignableFrom(c)) return en.getValue();
}
- return parent == null ? null : parent.findLoader(ft, field);
+ return parent == null ? null : parent.findRegxLoader(ft, field);
+ }
+
+ private ResourceLoader findLoader(Type ft, Field field) {
+ ResourceLoader it = this.findMatchLoader(ft, field);
+ return it == null ? findRegxLoader(ft, field) : it;
}
private static class ResourceEntry {