update spi
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
ehlxr 2021-02-09 22:45:13 +08:00
parent 5db4dbeba5
commit 10a11e2962
17 changed files with 93 additions and 347 deletions

View File

@ -1,80 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.did.extension;
import java.lang.annotation.*;
/**
* Activate
* <p/>
* 对于可以被框架中自动激活加载扩展此Annotation用于配置扩展被自动激活加载条件
* 比如过滤扩展有多个实现使用Activate Annotation的扩展可以根据条件被自动加载
* <p>
* <p/>
* 底层框架SPI提供者通过{@link ExtensionLoader}{@link ExtensionLoader#getActivateExtensions}方法
* 获得条件的扩展
*
* @see SPI
* @see ExtensionLoader
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Activate {
/**
* Group过滤条件
* <br />
* 包含{@link ExtensionLoader#getActivateExtensions}的group参数给的值则返回扩展
* <br />
* 如没有Group设置则不过滤
*/
String[] group() default {};
/**
* Key过滤条件包含{@link ExtensionLoader#getActivateExtensions}的URL的参数Key中有则返回扩展
* <p/>
* 示例<br/>
* 注解的值 <code>@Activate("cache,validatioin")</code>
* {@link ExtensionLoader#getActivateExtensions}的URL的参数有<code>cache</code>Key或是<code>validatioin</code>则返回扩展
* <br/>
* 如没有设置则不过滤
*/
String[] value() default {};
/**
* 排序信息可以不提供
*/
String[] before() default {};
/**
* 排序信息可以不提供
*/
String[] after() default {};
/**
* 排序信息可以不提供
*/
int order() default 0;
}

View File

@ -1,90 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.did.extension;
import java.util.Comparator;
/**
* Order Comparetor
*
* @author ehlxr
*/
public class ActivateComparator implements Comparator<Object> {
public static final Comparator<Object> COMPARATOR = new ActivateComparator();
@Override
public int compare(Object o1, Object o2) {
if (o1 == null && o2 == null) {
return 0;
}
if (o1 == null) {
return -1;
}
if (o2 == null) {
return 1;
}
if (o1.equals(o2)) {
return 0;
}
Activate a1 = o1.getClass().getAnnotation(Activate.class);
Activate a2 = o2.getClass().getAnnotation(Activate.class);
if ((a1.before().length > 0 || a1.after().length > 0
|| a2.before().length > 0 || a2.after().length > 0)
&& o1.getClass().getInterfaces().length > 0
&& o1.getClass().getInterfaces()[0].isAnnotationPresent(SPI.class)) {
ExtensionLoader<?> extensionLoader = ExtensionLoader.getExtensionLoader(o1.getClass().getInterfaces()[0]);
if (a1.before().length > 0 || a1.after().length > 0) {
String n2 = extensionLoader.getExtensionName(o2.getClass());
for (String before : a1.before()) {
if (before.equals(n2)) {
return -1;
}
}
for (String after : a1.after()) {
if (after.equals(n2)) {
return 1;
}
}
}
if (a2.before().length > 0 || a2.after().length > 0) {
String n1 = extensionLoader.getExtensionName(o1.getClass());
for (String before : a2.before()) {
if (before.equals(n1)) {
return 1;
}
}
for (String after : a2.after()) {
if (after.equals(n1)) {
return -1;
}
}
}
}
int n1 = a1.order();
int n2 = a2 == null ? 0 : a2.order();
return n1 > n2 ? 1 : -1;
}
}

View File

@ -1,40 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.did.extension;
import java.lang.annotation.*;
/**
* {@link ExtensionLoader}生成Extension的Adaptive Instance时{@link ExtensionLoader}提供信息
* 使用上类似于工厂方法
*
* @see ExtensionLoader
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Adaptive {
String[] value() default {};
}

View File

@ -32,7 +32,6 @@ import java.io.BufferedReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
@ -41,18 +40,16 @@ import java.util.concurrent.ConcurrentMap;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/** /**
* 加载和管理扩展 * 加载和管理扩展简化版 Dubbo SPI
* <p/> *
* <ul> * @author ehlxr
* <li>管理的扩展实例是<b>单例</b>
* <li>Wrapper实例每次获得扩展实例重新创建并Wrap到扩展实例上
* </ul>
*/ */
@SuppressWarnings("unused")
public class ExtensionLoader<T> { public class ExtensionLoader<T> {
private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.class); private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.class);
private static final String DUBBO_DIRECTORY = "META-INF/extensions/"; private static final String EXTENSIONS_DIRECTORY = "META-INF/extensions/";
private static final String DUBBO_INTERNAL_DIRECTORY = "META-INF/extensions/internal/"; private static final String EXTENSIONS_INTERNAL_DIRECTORY = "META-INF/extensions/internal/";
private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*,+\\s*"); private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*,+\\s*");
@ -63,25 +60,21 @@ public class ExtensionLoader<T> {
private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>(); private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();
private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>(); private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>();
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>(); private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();
private final Map<Class<?>, List<Object>> cachedActivates = new ConcurrentHashMap<>();
private final Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<>(); private final Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<>();
private String defaultExtension; private String defaultExtension;
private Set<Class<?>> cachedWrapperClasses;
private volatile Class<?> adaptiveClass = null;
private ExtensionLoader(Class<T> type) { private ExtensionLoader(Class<T> type) {
this.type = type; this.type = type;
} }
/** /**
* {@link ExtensionLoader}的工厂方法 * {@link ExtensionLoader} 的工厂方法
* *
* @param type 扩展点接口类型 * @param type 扩展点接口类型
* @param <T> 扩展点类型 * @param <T> 扩展点类型
* @return {@link ExtensionLoader}实例 * @return {@link ExtensionLoader} 实例
* @throws IllegalArgumentException 参数为<code>null</code> * @throws IllegalArgumentException 参数为 <code>null</code>
* 或是扩展点接口上没有{@link SPI}注解 * 或是扩展点接口上没有 {@link SPI} 注解
* @since 0.1.0
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) { public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
@ -91,7 +84,7 @@ public class ExtensionLoader<T> {
if (!type.isInterface()) { if (!type.isInterface()) {
throw new IllegalArgumentException("SPI type(" + type.getName() + ") is not interface!"); throw new IllegalArgumentException("SPI type(" + type.getName() + ") is not interface!");
} }
if (!withExtensionAnnotation(type)) { if (!type.isAnnotationPresent(SPI.class)) {
throw new IllegalArgumentException("type(" + type.getName() + throw new IllegalArgumentException("type(" + type.getName() +
") is not a extension, because WITHOUT @SPI Annotation!"); ") is not a extension, because WITHOUT @SPI Annotation!");
} }
@ -104,10 +97,6 @@ public class ExtensionLoader<T> {
return loader; return loader;
} }
private static <T> boolean withExtensionAnnotation(Class<T> type) {
return type.isAnnotationPresent(SPI.class);
}
/** /**
* Get the String of Throwable, like the output of {@link Throwable#printStackTrace()}. * Get the String of Throwable, like the output of {@link Throwable#printStackTrace()}.
* *
@ -121,10 +110,6 @@ public class ExtensionLoader<T> {
} }
} }
public static <T> T getExtension(Class<T> clazz, String value) {
return getExtensionLoader(clazz).getExtension(value);
}
public T getExtension(String name) { public T getExtension(String name) {
if (StringUtil.isNullOrEmpty(name)) { if (StringUtil.isNullOrEmpty(name)) {
throw new IllegalArgumentException("SPI name == null"); throw new IllegalArgumentException("SPI name == null");
@ -146,6 +131,7 @@ public class ExtensionLoader<T> {
} }
} }
} }
//noinspection unchecked
return (T) instance; return (T) instance;
} }
@ -153,7 +139,6 @@ public class ExtensionLoader<T> {
* 返回缺省的扩展 * 返回缺省的扩展
* *
* @throws IllegalStateException 指定的扩展没有设置缺省扩展点 * @throws IllegalStateException 指定的扩展没有设置缺省扩展点
* @since 0.1.0
*/ */
public T getDefaultExtension() { public T getDefaultExtension() {
loadExtensionClasses0(); loadExtensionClasses0();
@ -174,21 +159,6 @@ public class ExtensionLoader<T> {
return Collections.unmodifiableSet(new HashSet<>(classes.keySet())); return Collections.unmodifiableSet(new HashSet<>(classes.keySet()));
} }
/**
* get active extension points
*
* @return extension list which are activated.
*/
public List<T> getActivateExtensions() {
getExtensionClasses();
// TODO {group value} filter
List<T> activates = (List<T>) cachedActivates.get(type);
activates.sort(ActivateComparator.COMPARATOR);
return activates;
}
public String getExtensionName(Class<?> spi) { public String getExtensionName(Class<?> spi) {
getExtensionClasses(); getExtensionClasses();
return cachedNames.get(spi); return cachedNames.get(spi);
@ -200,16 +170,14 @@ public class ExtensionLoader<T> {
throw findExtensionClassLoadException(name); throw findExtensionClassLoadException(name);
} }
try { try {
//noinspection unchecked
T instance = (T) EXTENSION_INSTANCES.get(clazz); T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) { if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
//noinspection unchecked
instance = (T) EXTENSION_INSTANCES.get(clazz); instance = (T) EXTENSION_INSTANCES.get(clazz);
} }
// TODO 支持组件自动注入
// TODO 支持wrapper类包装实现aop相似的功能
return instance; return instance;
} catch (Throwable t) { } catch (Throwable t) {
throw new IllegalStateException("SPI instance(name: " + name + ", class: " + throw new IllegalStateException("SPI instance(name: " + name + ", class: " +
@ -217,9 +185,6 @@ public class ExtensionLoader<T> {
} }
} }
/**
* Thread-safe.
*/
private Map<String, Class<?>> getExtensionClasses() { private Map<String, Class<?>> getExtensionClasses() {
Map<String, Class<?>> classes = cachedClasses.get(); Map<String, Class<?>> classes = cachedClasses.get();
if (classes == null) { if (classes == null) {
@ -275,8 +240,8 @@ public class ExtensionLoader<T> {
} }
Map<String, Class<?>> extensionClasses = new HashMap<>(); Map<String, Class<?>> extensionClasses = new HashMap<>();
loadFile(extensionClasses, DUBBO_DIRECTORY); loadFile(extensionClasses, EXTENSIONS_DIRECTORY);
loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY); loadFile(extensionClasses, EXTENSIONS_INTERNAL_DIRECTORY);
cachedClasses.set(extensionClasses); cachedClasses.set(extensionClasses);
} }
@ -284,7 +249,6 @@ public class ExtensionLoader<T> {
String fileName = dir + type.getName(); String fileName = dir + type.getName();
try { try {
Enumeration<URL> urls; Enumeration<URL> urls;
ClassLoader classLoader = ExtensionLoader.class.getClassLoader(); ClassLoader classLoader = ExtensionLoader.class.getClassLoader();
if (classLoader != null) { if (classLoader != null) {
urls = classLoader.getResources(fileName); urls = classLoader.getResources(fileName);
@ -296,7 +260,9 @@ public class ExtensionLoader<T> {
while (urls.hasMoreElements()) { while (urls.hasMoreElements()) {
URL url = urls.nextElement(); URL url = urls.nextElement();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) { try (
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))
) {
String line; String line;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
// delete comments // delete comments
@ -311,7 +277,6 @@ public class ExtensionLoader<T> {
try { try {
String name = null; String name = null;
int i = line.indexOf('='); int i = line.indexOf('=');
if (i > 0) { if (i > 0) {
@ -327,66 +292,40 @@ public class ExtensionLoader<T> {
+ clazz.getName() + "is not subtype of interface."); + clazz.getName() + "is not subtype of interface.");
} }
if (clazz.isAnnotationPresent(Adaptive.class)) { if (name == null || name.length() == 0) {
if (adaptiveClass == null) { // clazz: xxx.xxx.ZfyAPI
adaptiveClass = clazz; // type: xxx.xxx.API
} else if (!adaptiveClass.equals(clazz)) { // -> name: zfy
throw new IllegalStateException("More than 1 adaptive class found: " if (clazz.getSimpleName().length() > type.getSimpleName().length()
+ adaptiveClass.getName() && clazz.getSimpleName().endsWith(type.getSimpleName())) {
+ ", " + clazz.getName()); name = clazz.getSimpleName().substring(0, clazz.getSimpleName().length()
- type.getSimpleName().length()).toLowerCase();
} else {
throw new IllegalStateException("No such extension name for the class "
+ clazz.getName() + " in the config " + url);
} }
} else { }
try {
clazz.getConstructor(type);
Set<Class<?>> wrappers = cachedWrapperClasses;
if (wrappers == null) {
cachedWrapperClasses = new HashSet<>();
wrappers = cachedWrapperClasses;
}
wrappers.add(clazz);
} catch (NoSuchMethodException e) {
Constructor<? extends T> constructor = clazz.getConstructor();
if (name == null || name.length() == 0) {
if (clazz.getSimpleName().length() > type.getSimpleName().length()
&& clazz.getSimpleName().endsWith(type.getSimpleName())) {
name = clazz.getSimpleName().substring(0, clazz.getSimpleName().length() - type.getSimpleName().length()).toLowerCase();
} else {
throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + url);
}
}
Activate activate = clazz.getAnnotation(Activate.class);
if (activate != null) { if (!cachedNames.containsKey(clazz)) {
List<Object> activates = cachedActivates.get(type); cachedNames.put(clazz, name);
if (activates == null) { }
synchronized (cachedActivates) {
activates = new ArrayList<>();
}
}
activates.add(constructor.newInstance()); Class<?> c = extensionClasses.get(name);
cachedActivates.put(type, activates); if (c == null) {
} extensionClasses.put(name, clazz);
} else if (c != clazz) {
if (!cachedNames.containsKey(clazz)) { throw new IllegalStateException("Duplicate extension "
cachedNames.put(clazz, name); + type.getName() + " name " + name + " on " + c.getName()
} + " and " + clazz.getName());
Class<?> c = extensionClasses.get(name);
if (c == null) {
extensionClasses.put(name, clazz);
} else if (c != clazz) {
throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + name + " on " + c.getName() + " and " + clazz.getName());
}
}
} }
} }
} catch (Throwable t) { } catch (Throwable t) {
IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t); IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: "
+ type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t);
exceptions.put(line, e); exceptions.put(line, e);
} }
} // end of while read lines }
} catch (Throwable t) { } catch (Throwable t) {
logger.error("Exception when load extension class(interface: " + logger.error("Exception when load extension class(interface: " +
type + ", class file: " + url + ") in " + url, t); type + ", class file: " + url + ") in " + url, t);
@ -406,9 +345,8 @@ public class ExtensionLoader<T> {
/** /**
* Holds a value of type <code>T</code>. * Holds a value of type <code>T</code>.
*
* @since 0.1.0
*/ */
@SuppressWarnings("unused")
private static final class Holder<T> { private static final class Holder<T> {
/** /**
* The value contained in the holder. * The value contained in the holder.

View File

@ -28,11 +28,11 @@ import java.lang.annotation.*;
/** /**
* 把一个接口标识成扩展点 * 把一个接口标识成扩展点
* <p/> * <p>
* 没有此注释的接口{@link ExtensionLoader}会拒绝接管 * 没有此注释的接口 {@link ExtensionLoader} 会拒绝接管
* *
* @author ehlxr
* @see ExtensionLoader * @see ExtensionLoader
* @since 0.1.0
*/ */
@Documented @Documented
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ -41,9 +41,6 @@ public @interface SPI {
/** /**
* the default extension name. * the default extension name.
*
* @since 0.1.0
*/ */
String value() default ""; String value() default "";
} }

View File

@ -37,7 +37,7 @@ import java.util.concurrent.ConcurrentHashMap;
* @author ehlxr * @author ehlxr
* @since 2021-02-09 11:07. * @since 2021-02-09 11:07.
*/ */
public class ProtobufSerializer implements Serializer { public class ProtostuffSerializer implements Serializer {
private static final Map<Class<?>, Schema<?>> CACHED_SCHEMA = new ConcurrentHashMap<>(); private static final Map<Class<?>, Schema<?>> CACHED_SCHEMA = new ConcurrentHashMap<>();
@Override @Override

View File

@ -6,7 +6,7 @@ import io.github.ehlxr.did.extension.SPI;
* @author ehlxr * @author ehlxr
* @since 2021-02-08 22:12. * @since 2021-02-08 22:12.
*/ */
@SPI("jdk") @SPI("protostuff")
public interface Serializer { public interface Serializer {
/** /**
* obj 序列化成 byte 数组 * obj 序列化成 byte 数组

View File

@ -1,6 +1,13 @@
package io.github.ehlxr.did.serializer; package io.github.ehlxr.did.serializer;
import io.github.ehlxr.did.common.Constants;
import io.github.ehlxr.did.extension.ExtensionLoader; import io.github.ehlxr.did.extension.ExtensionLoader;
import io.netty.util.internal.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects;
import java.util.Set;
/** /**
* @author ehlxr * @author ehlxr
@ -8,6 +15,7 @@ import io.github.ehlxr.did.extension.ExtensionLoader;
*/ */
public final class SerializerHolder { public final class SerializerHolder {
volatile private static Serializer serializer = null; volatile private static Serializer serializer = null;
private static final Logger logger = LoggerFactory.getLogger(SerializerHolder.class);
private SerializerHolder() { private SerializerHolder() {
} }
@ -16,7 +24,15 @@ public final class SerializerHolder {
if (serializer == null) { if (serializer == null) {
synchronized (SerializerHolder.class) { synchronized (SerializerHolder.class) {
if (serializer == null) { if (serializer == null) {
serializer = ExtensionLoader.getExtensionLoader(Serializer.class).getDefaultExtension(); String serializerName = Constants.getEnv("DID_SERIALIZER");
if (!StringUtil.isNullOrEmpty(serializerName)) {
serializer = ExtensionLoader.getExtensionLoader(Serializer.class).getExtension(serializerName);
}
serializer = Objects.isNull(serializer) ?
ExtensionLoader.getExtensionLoader(Serializer.class).getDefaultExtension() :
serializer;
logger.debug("loaded {} serializer", serializer.getClass().getName());
} }
} }
} }

View File

@ -1,2 +1,3 @@
jdk=io.github.ehlxr.did.serializer.JdkSerializer #protostuff1=io.github.ehlxr.did.serializer.ProtostuffSerializer
protobuf=io.github.ehlxr.did.serializer.ProtobufSerializer protostuff=io.github.ehlxr.did.serializer.ProtostuffSerializer
io.github.ehlxr.did.serializer.JdkSerializer

View File

@ -1,10 +1,13 @@
package io.github.ehlxr.did; package io.github.ehlxr.did;
import io.github.ehlxr.did.client.SdkClient; import io.github.ehlxr.did.client.SdkClient;
import io.github.ehlxr.did.common.Try;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream; import java.util.stream.IntStream;
/** /**
@ -34,16 +37,16 @@ public class DidSdkTest {
System.out.println("invokeync test finish"); System.out.println("invokeync test finish");
// 测试异步请求 // 测试异步请求
// final CountDownLatch countDownLatch = new CountDownLatch(NUM); final CountDownLatch countDownLatch = new CountDownLatch(NUM);
// IntStream.range(0, NUM).parallel().forEach(i -> IntStream.range(0, NUM).parallel().forEach(i ->
// Try.of(() -> client.invokeAsync(responseFuture -> { Try.of(() -> client.invokeAsync(responseFuture -> {
// System.out.println(responseFuture.getSdkProto()); System.out.println(responseFuture.getSdkProto());
// countDownLatch.countDown(); countDownLatch.countDown();
// })).trap(Throwable::printStackTrace).run()); })).trap(Throwable::printStackTrace).run());
//
// //noinspection ResultOfMethodCallIgnored //noinspection ResultOfMethodCallIgnored
// countDownLatch.await(10, TimeUnit.SECONDS); countDownLatch.await(10, TimeUnit.SECONDS);
// System.out.println("invokeAsync test finish"); System.out.println("invokeAsync test finish");
} }
@Test @Test

View File

@ -1,6 +1,7 @@
package io.github.ehlxr.did; package io.github.ehlxr.did;
import io.github.ehlxr.did.common.Constants; import io.github.ehlxr.did.common.Constants;
import io.github.ehlxr.did.generator.SnowFlake;
import io.github.ehlxr.did.server.Server; import io.github.ehlxr.did.server.Server;
import io.github.ehlxr.did.server.http.HttpServer; import io.github.ehlxr.did.server.http.HttpServer;
import io.github.ehlxr.did.server.sdk.SdkServer; import io.github.ehlxr.did.server.sdk.SdkServer;

View File

@ -1,4 +1,4 @@
package io.github.ehlxr.did; package io.github.ehlxr.did.generator;
/** /**
* twitter snowflake 算法 -- java 实现 * twitter snowflake 算法 -- java 实现

View File

@ -1,6 +1,6 @@
package io.github.ehlxr.did.server; package io.github.ehlxr.did.server;
import io.github.ehlxr.did.SnowFlake; import io.github.ehlxr.did.generator.SnowFlake;
import io.github.ehlxr.did.common.Try; import io.github.ehlxr.did.common.Try;
import io.netty.bootstrap.ServerBootstrap; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFuture;

View File

@ -1,6 +1,6 @@
package io.github.ehlxr.did.server.http; package io.github.ehlxr.did.server.http;
import io.github.ehlxr.did.SnowFlake; import io.github.ehlxr.did.generator.SnowFlake;
import io.github.ehlxr.did.common.Constants; import io.github.ehlxr.did.common.Constants;
import io.github.ehlxr.did.common.Try; import io.github.ehlxr.did.common.Try;
import io.github.ehlxr.did.server.BaseServer; import io.github.ehlxr.did.server.BaseServer;

View File

@ -1,7 +1,7 @@
package io.github.ehlxr.did.server.http; package io.github.ehlxr.did.server.http;
import io.github.ehlxr.did.SdkProto; import io.github.ehlxr.did.SdkProto;
import io.github.ehlxr.did.SnowFlake; import io.github.ehlxr.did.generator.SnowFlake;
import io.github.ehlxr.did.common.Constants; import io.github.ehlxr.did.common.Constants;
import io.github.ehlxr.did.common.NettyUtil; import io.github.ehlxr.did.common.NettyUtil;
import io.github.ehlxr.did.common.Result; import io.github.ehlxr.did.common.Result;
@ -66,14 +66,14 @@ public class HttpServerHandler extends SimpleChannelInboundHandler<FullHttpReque
response.setStatus(status) response.setStatus(status)
.content().writeBytes(result.toString().getBytes()); .content().writeBytes(result.toString().getBytes());
logger.debug("http server handler write response {} restul {} to channel", status, result); logger.debug("http server handler write response {} result {} to channel", status, result);
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
} }
@Override @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
Channel channel = ctx.channel(); Channel channel = ctx.channel();
logger.error("HttpServerHandler channel [{}] error and will be closed", NettyUtil.parseRemoteAddr(channel), cause); logger.error("channel {} will be closed, 'cause of ", NettyUtil.parseRemoteAddr(channel), cause);
NettyUtil.closeChannel(channel); NettyUtil.closeChannel(channel);
} }
} }

View File

@ -1,6 +1,6 @@
package io.github.ehlxr.did.server.sdk; package io.github.ehlxr.did.server.sdk;
import io.github.ehlxr.did.SnowFlake; import io.github.ehlxr.did.generator.SnowFlake;
import io.github.ehlxr.did.adapter.MessageDecoder; import io.github.ehlxr.did.adapter.MessageDecoder;
import io.github.ehlxr.did.adapter.MessageEncoder; import io.github.ehlxr.did.adapter.MessageEncoder;
import io.github.ehlxr.did.common.Constants; import io.github.ehlxr.did.common.Constants;

View File

@ -1,10 +1,10 @@
package io.github.ehlxr.did.server.sdk; package io.github.ehlxr.did.server.sdk;
import io.github.ehlxr.did.SdkProto; import io.github.ehlxr.did.SdkProto;
import io.github.ehlxr.did.SnowFlake;
import io.github.ehlxr.did.adapter.Message; import io.github.ehlxr.did.adapter.Message;
import io.github.ehlxr.did.common.Constants; import io.github.ehlxr.did.common.Constants;
import io.github.ehlxr.did.common.NettyUtil; import io.github.ehlxr.did.common.NettyUtil;
import io.github.ehlxr.did.generator.SnowFlake;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
@ -56,7 +56,7 @@ public class SdkServerHandler extends SimpleChannelInboundHandler<Message<SdkPro
@Override @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
Channel channel = ctx.channel(); Channel channel = ctx.channel();
logger.error("SdkServerHandler channel [{}] error and will be closed", NettyUtil.parseRemoteAddr(channel), cause); logger.error("channel {} will be closed, 'cause of ", NettyUtil.parseRemoteAddr(channel), cause);
NettyUtil.closeChannel(channel); NettyUtil.closeChannel(channel);
} }
} }