This commit is contained in:
RedKale
2016-06-26 14:08:35 +08:00
parent 999f55222b
commit 511a31bf95
5 changed files with 129 additions and 42 deletions

View File

@@ -14,13 +14,12 @@ import java.util.concurrent.*;
import java.util.jar.*; import java.util.jar.*;
import java.util.logging.*; import java.util.logging.*;
import java.util.regex.*; import java.util.regex.*;
import org.redkale.util.AnyValue; import org.redkale.util.*;
import org.redkale.util.AnyValue.DefaultAnyValue; import org.redkale.util.AnyValue.DefaultAnyValue;
import org.redkale.util.AutoLoad;
/** /**
* class过滤器 符合条件的class会保留下来存入FilterEntry。 * class过滤器 符合条件的class会保留下来存入FilterEntry。
* * <p>
* <p> * <p>
* 详情见: http://redkale.org * 详情见: http://redkale.org
* *
@@ -30,8 +29,14 @@ import org.redkale.util.AutoLoad;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class ClassFilter<T> { public final class ClassFilter<T> {
private static final Logger logger = Logger.getLogger(ClassFilter.class.getName());
private static final boolean finer = logger.isLoggable(Level.FINER);
private final Set<FilterEntry<T>> entrys = new HashSet<>(); private final Set<FilterEntry<T>> entrys = new HashSet<>();
private final Set<FilterEntry<T>> expectEntrys = new HashSet<>();
private boolean refused; private boolean refused;
private Class superClass; private Class superClass;
@@ -79,10 +84,31 @@ public final class ClassFilter<T> {
return entrys; return entrys;
} }
/**
* 获取预留的class集合
*
* @return Set&lt;FilterEntry&lt;T&gt;&gt;
*/
public final Set<FilterEntry<T>> getFilterExpectEntrys() {
return expectEntrys;
}
/**
* 获取所有的class集合
*
* @return Set&lt;FilterEntry&lt;T&gt;&gt;
*/
public final Set<FilterEntry<T>> getAllFilterEntrys() {
HashSet<FilterEntry<T>> rs = new HashSet<>();
rs.addAll(entrys);
rs.addAll(expectEntrys);
return rs;
}
/** /**
* 自动扫描地过滤指定的class * 自动扫描地过滤指定的class
* *
* @param property AnyValue * @param property AnyValue
* @param clazzname String * @param clazzname String
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -93,9 +119,9 @@ public final class ClassFilter<T> {
/** /**
* 过滤指定的class * 过滤指定的class
* *
* @param property application.xml中对应class节点下的property属性项 * @param property application.xml中对应class节点下的property属性项
* @param clazzname class名称 * @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) { public final void filter(AnyValue property, String clazzname, boolean autoscan) {
boolean r = accept0(property, clazzname); boolean r = accept0(property, clazzname);
@@ -129,8 +155,15 @@ public final class ClassFilter<T> {
property = dav; 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) { } catch (Throwable cfe) {
if (finer) logger.log(Level.FINER, ClassFilter.class.getSimpleName() + " filter error", cfe);
} }
} }
@@ -152,8 +185,9 @@ public final class ClassFilter<T> {
/** /**
* 判断class是否有效 * 判断class是否有效
* *
* @param property AnyValue * @param property AnyValue
* @param classname String * @param classname String
*
* @return boolean * @return boolean
*/ */
public boolean accept(AnyValue property, String classname) { public boolean accept(AnyValue property, String classname) {
@@ -191,17 +225,14 @@ public final class ClassFilter<T> {
* 判断class是否有效 * 判断class是否有效
* *
* @param property AnyValue * @param property AnyValue
* @param clazz Class * @param clazz Class
* @param autoscan boolean * @param autoscan boolean
*
* @return boolean * @return boolean
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public boolean accept(AnyValue property, Class clazz, boolean autoscan) { public boolean accept(AnyValue property, Class clazz, boolean autoscan) {
if (this.refused || !Modifier.isPublic(clazz.getModifiers())) return false; 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; if (annotationClass != null && clazz.getAnnotation(annotationClass) == null) return false;
return superClass == null || (clazz != superClass && superClass.isAssignableFrom(clazz)); return superClass == null || (clazz != superClass && superClass.isAssignableFrom(clazz));
} }
@@ -263,11 +294,13 @@ public final class ClassFilter<T> {
private final boolean autoload; private final boolean autoload;
private final boolean expect;
public FilterEntry(Class<T> type, AnyValue property) { public FilterEntry(Class<T> type, AnyValue property) {
this(type, false, property); this(type, false, false, property);
} }
public FilterEntry(Class<T> type, final boolean autoload, AnyValue property) { public FilterEntry(Class<T> type, final boolean autoload, boolean expect, AnyValue property) {
this.type = type; this.type = type;
String str = property == null ? null : property.getValue("groups"); String str = property == null ? null : property.getValue("groups");
if (str != null) { if (str != null) {
@@ -277,6 +310,7 @@ public final class ClassFilter<T> {
if (str != null) groups.addAll(Arrays.asList(str.split(";"))); if (str != null) groups.addAll(Arrays.asList(str.split(";")));
this.property = property; this.property = property;
this.autoload = autoload; this.autoload = autoload;
this.expect = expect;
this.name = property == null ? "" : property.getValue("name", ""); this.name = property == null ? "" : property.getValue("name", "");
} }
@@ -322,6 +356,9 @@ public final class ClassFilter<T> {
return autoload; return autoload;
} }
public boolean isExpect() {
return expect;
}
} }
/** /**
@@ -342,6 +379,7 @@ public final class ClassFilter<T> {
* *
* @param exclude 不需要扫描的文件夹, 可以为null * @param exclude 不需要扫描的文件夹, 可以为null
* @param filters 过滤器 * @param filters 过滤器
*
* @throws IOException 异常 * @throws IOException 异常
*/ */
public static void load(final File exclude, final ClassFilter... filters) throws IOException { public static void load(final File exclude, final ClassFilter... filters) throws IOException {

View File

@@ -21,6 +21,7 @@ import javax.persistence.Transient;
import static org.redkale.boot.Application.*; import static org.redkale.boot.Application.*;
import org.redkale.boot.ClassFilter.FilterEntry; import org.redkale.boot.ClassFilter.FilterEntry;
import org.redkale.net.*; import org.redkale.net.*;
import org.redkale.net.http.WebSocketNode;
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.*;
@@ -249,13 +250,21 @@ public abstract class NodeServer {
protected void loadService(ClassFilter serviceFilter) throws Exception { protected void loadService(ClassFilter serviceFilter) throws Exception {
if (serviceFilter == null) return; if (serviceFilter == null) return;
final String threadName = "[" + Thread.currentThread().getName() + "] "; final String threadName = "[" + Thread.currentThread().getName() + "] ";
final Set<FilterEntry<Service>> entrys = serviceFilter.getFilterEntrys(); final Set<FilterEntry<Service>> entrys = serviceFilter.getAllFilterEntrys();
ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : resourceFactory; ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : resourceFactory;
for (FilterEntry<Service> entry : entrys) { //service实现类 for (FilterEntry<Service> entry : entrys) { //service实现类
final Class<? extends Service> type = entry.getType(); final Class<? extends Service> type = entry.getType();
if (Modifier.isFinal(type.getModifiers())) continue; //修饰final的类跳过 if (Modifier.isFinal(type.getModifiers())) continue; //修饰final的类跳过
if (!Modifier.isPublic(type.getModifiers())) continue; 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("<name> value cannot contains '$' in " + entry.getProperty()); if (entry.getName().contains("$")) throw new RuntimeException("<name> value cannot contains '$' in " + entry.getProperty());
if (resourceFactory.find(entry.getName(), type) != null) continue; //Server加载Service时需要判断是否已经加载过了。 if (resourceFactory.find(entry.getName(), type) != null) continue; //Server加载Service时需要判断是否已经加载过了。
final HashSet<String> groups = entry.getGroups(); //groups.isEmpty()表示<services>没有配置groups属性。 final HashSet<String> groups = entry.getGroups(); //groups.isEmpty()表示<services>没有配置groups属性。
@@ -266,29 +275,52 @@ public abstract class NodeServer {
|| (this.sncpGroup == null && entry.isEmptyGroups()) //空的SNCP配置 || (this.sncpGroup == null && entry.isEmptyGroups()) //空的SNCP配置
|| type.getAnnotation(LocalService.class) != null;//本地模式 || type.getAnnotation(LocalService.class) != null;//本地模式
if (localed && (type.isInterface() || Modifier.isAbstract(type.getModifiers()))) continue; //本地模式不能实例化接口和抽象类的Service类 if (localed && (type.isInterface() || Modifier.isAbstract(type.getModifiers()))) continue; //本地模式不能实例化接口和抽象类的Service类
final Runnable runner = new Runnable() {
Service service; @Override
if (localed) { //本地模式 public void run() {
service = Sncp.createLocalService(entry.getName(), getExecutor(), application.getResourceFactory(), type, this.sncpAddress, loadTransport(this.sncpGroup), loadTransports(groups)); try {
} else { Service service;
service = Sncp.createRemoteService(entry.getName(), getExecutor(), type, this.sncpAddress, loadTransport(groups)); if (localed) { //本地模式
} service = Sncp.createLocalService(entry.getName(), getExecutor(), application.getResourceFactory(), type,
if (SncpClient.parseMethod(type).isEmpty()) continue; //class没有可用的方法 通常为BaseService NodeServer.this.sncpAddress, loadTransport(NodeServer.this.sncpGroup), loadTransports(groups));
final ServiceWrapper wrapper = new ServiceWrapper(type, service, entry.getName(), localed ? this.sncpGroup : null, groups, entry.getProperty()); } else {
for (final Class restype : wrapper.getTypes()) { service = Sncp.createRemoteService(entry.getName(), getExecutor(), type, NodeServer.this.sncpAddress, loadTransport(groups));
if (resourceFactory.find(wrapper.getName(), restype) == null) { }
regFactory.register(wrapper.getName(), restype, wrapper.getService()); if (SncpClient.parseMethod(type).isEmpty()) return; //class没有可用的方法 通常为BaseService
} else if (isSNCP() && !entry.isAutoload()) { final ServiceWrapper wrapper = new ServiceWrapper(type, service, entry.getName(), localed ? NodeServer.this.sncpGroup : null, groups, entry.getProperty());
throw new RuntimeException(ServiceWrapper.class.getSimpleName() + "(class:" + type.getName() + ", name:" + entry.getName() + ", group:" + groups + ") is repeat."); 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 { } else {
localServiceWrappers.add(wrapper); runner.run();
if (consumer != null) consumer.accept(wrapper);
} }
} }
application.servicecdl.countDown(); application.servicecdl.countDown();
application.servicecdl.await(); application.servicecdl.await();
@@ -297,12 +329,14 @@ public abstract class NodeServer {
new ArrayList<>(localServiceWrappers).forEach(y -> { new ArrayList<>(localServiceWrappers).forEach(y -> {
resourceFactory.inject(y.getService(), NodeServer.this); resourceFactory.inject(y.getService(), NodeServer.this);
}); });
remoteServiceWrappers.forEach(y -> { new ArrayList<>(remoteServiceWrappers).forEach(y -> {
resourceFactory.inject(y.getService(), NodeServer.this); 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 ----------------- //----------------- init -----------------
List<ServiceWrapper> swlist = new ArrayList<>(localServiceWrappers); List<ServiceWrapper> swlist = new ArrayList<>(localServiceWrappers);
Collections.sort(swlist); Collections.sort(swlist);

View File

@@ -66,6 +66,11 @@ public final class ServiceWrapper<T extends Service> implements Comparable<Servi
maxClassNameLength = Math.max(maxClassNameLength, s.length() + 1); maxClassNameLength = Math.max(maxClassNameLength, s.length() + 1);
} }
public static Class[] parseTypes(final Class<? extends Service> servicetype) {
ResourceType rty = servicetype.getAnnotation(ResourceType.class);
return rty == null ? new Class[]{servicetype} : rty.value();
}
public String toSimpleString() { public String toSimpleString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(remote ? "RemoteService" : "LocalService "); sb.append(remote ? "RemoteService" : "LocalService ");

View File

@@ -11,7 +11,7 @@ import java.lang.annotation.*;
/** /**
* 自动加载。 使用场景: * 自动加载。 使用场景:
* 1、被标记为@AutoLoad(false)的Service类不会被自动加载 * 1、被标记为@AutoLoad(false)的Service类不会被自动加载, 当被依赖时才会被加载
* 2、被标记为@AutoLoad(false)的Servlet类不会被自动加载 * 2、被标记为@AutoLoad(false)的Servlet类不会被自动加载
* *
* <p> 详情见: http://redkale.org * <p> 详情见: http://redkale.org

View File

@@ -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); ResourceLoader it = this.loadermap.get(ft);
if (it == null) it = this.loadermap.get(field.getType());
if (it != null) return it; if (it != null) return it;
return parent == null ? null : parent.findMatchLoader(ft, field);
}
private ResourceLoader findRegxLoader(Type ft, Field field) {
Class c = field.getType(); Class c = field.getType();
for (Map.Entry<Type, ResourceLoader> en : this.loadermap.entrySet()) { for (Map.Entry<Type, ResourceLoader> en : this.loadermap.entrySet()) {
Type t = en.getKey(); Type t = en.getKey();
if (t == ft) return en.getValue(); if (t == ft) return en.getValue();
if (t instanceof Class && (((Class) t)).isAssignableFrom(c)) 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<T> { private static class ResourceEntry<T> {