This commit is contained in:
@@ -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<FilterEntry<T>>
|
||||||
|
*/
|
||||||
|
public final Set<FilterEntry<T>> getFilterExpectEntrys() {
|
||||||
|
return expectEntrys;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有的class集合
|
||||||
|
*
|
||||||
|
* @return Set<FilterEntry<T>>
|
||||||
|
*/
|
||||||
|
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 {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 ");
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
Reference in New Issue
Block a user