sncp
This commit is contained in:
@@ -53,13 +53,13 @@ public abstract class SncpActionServlet extends SncpServlet {
|
||||
|
||||
protected final Class<? extends CompletionHandler> paramHandlerClass; // CompletionHandler参数的类型
|
||||
|
||||
protected final java.lang.reflect.Type paramHandlerResultType; // CompletionHandler.completed第一个参数的类型
|
||||
protected final java.lang.reflect.Type paramHandlerType; // CompletionHandler.completed第一个参数的类型
|
||||
|
||||
@ClassDepends
|
||||
protected final java.lang.reflect.Type returnObjectType; // 返回结果类型 void必须设为null
|
||||
|
||||
@ClassDepends
|
||||
protected final java.lang.reflect.Type returnFutureResultType; // 返回结果的CompletableFuture的结果泛型类型
|
||||
protected final java.lang.reflect.Type returnFutureType; // 返回结果的CompletableFuture的结果泛型类型
|
||||
|
||||
@ClassDepends
|
||||
protected SncpActionServlet(
|
||||
@@ -119,7 +119,7 @@ public abstract class SncpActionServlet extends SncpServlet {
|
||||
this.paramTypes = types;
|
||||
this.paramHandlerIndex = handlerFuncIndex;
|
||||
this.paramHandlerClass = handlerFuncClass;
|
||||
this.paramHandlerResultType = handlerResultType;
|
||||
this.paramHandlerType = handlerResultType;
|
||||
this.returnObjectType =
|
||||
originalReturnType == void.class || originalReturnType == Void.class ? null : originalReturnType;
|
||||
if (Future.class.isAssignableFrom(method.getReturnType())) {
|
||||
@@ -134,9 +134,9 @@ public abstract class SncpActionServlet extends SncpServlet {
|
||||
} else {
|
||||
throw new SncpException(service.getClass() + " had unknown return genericType in " + method);
|
||||
}
|
||||
this.returnFutureResultType = returnType;
|
||||
this.returnFutureType = returnType;
|
||||
} else {
|
||||
this.returnFutureResultType = null;
|
||||
this.returnFutureType = null;
|
||||
}
|
||||
NonBlocking non = method.getAnnotation(NonBlocking.class);
|
||||
if (non == null) {
|
||||
@@ -150,7 +150,7 @@ public abstract class SncpActionServlet extends SncpServlet {
|
||||
@Override
|
||||
public final void execute(SncpRequest request, SncpResponse response) throws IOException {
|
||||
if (paramHandlerIndex > 0) {
|
||||
response.paramAsyncHandler(paramHandlerClass, paramHandlerResultType);
|
||||
response.paramAsyncHandler(paramHandlerClass, paramHandlerType);
|
||||
}
|
||||
try {
|
||||
action(request, response);
|
||||
@@ -194,7 +194,7 @@ public abstract class SncpActionServlet extends SncpServlet {
|
||||
*
|
||||
* public void update(long show, short v2, CompletionHandler<Boolean, TestBean> handler, TestBean bean, String name, int id);
|
||||
*
|
||||
* public CompletableFuture<String> changeName(TestBean bean, String name, int id);
|
||||
* public CompletableFuture<String> changeName(TestBean bean, String name, int id);
|
||||
*
|
||||
* }
|
||||
*
|
||||
@@ -304,14 +304,14 @@ public abstract class SncpActionServlet extends SncpServlet {
|
||||
* @Override
|
||||
* public void action(SncpRequest request, SncpResponse response) throws Throwable {
|
||||
* Convert<Reader, Writer> convert = request.getConvert();
|
||||
* Reader in = request.getReader();
|
||||
* TestBean arg1 = convert.convertFrom(paramTypes[1], in);
|
||||
* String arg2 = convert.convertFrom(paramTypes[2], in);
|
||||
* int arg3 = convert.convertFrom(paramTypes[3], in);
|
||||
* TestService serviceObj = (TestService) service();
|
||||
* CompletableFuture future = serviceObj.changeName(arg1, arg2, arg3);
|
||||
* response.finishFuture(paramHandlerResultType, future);
|
||||
* }
|
||||
* Reader in = request.getReader();
|
||||
* TestBean arg1 = convert.convertFrom(paramTypes[1], in);
|
||||
* String arg2 = convert.convertFrom(paramTypes[2], in);
|
||||
* int arg3 = convert.convertFrom(paramTypes[3], in);
|
||||
* TestService serviceObj = (TestService) service();
|
||||
* CompletableFuture future = serviceObj.changeName(arg1, arg2, arg3);
|
||||
* response.finishFuture(paramHandlerType, future);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* </pre>
|
||||
@@ -349,6 +349,9 @@ public abstract class SncpActionServlet extends SncpServlet {
|
||||
final String requestDesc = Type.getDescriptor(SncpRequest.class);
|
||||
final String responseDesc = Type.getDescriptor(SncpResponse.class);
|
||||
final String serviceDesc = Type.getDescriptor(Service.class);
|
||||
final String handlerDesc = Type.getDescriptor(CompletionHandler.class);
|
||||
final String futureDesc = Type.getDescriptor(Future.class);
|
||||
final String reflectTypeDesc = Type.getDescriptor(java.lang.reflect.Type.class);
|
||||
final boolean boolReturnTypeFuture = Future.class.isAssignableFrom(method.getReturnType());
|
||||
final String newDynName = "org/redkaledyn/sncp/servlet/action/_DynSncpActionServlet__"
|
||||
+ resourceType.getSimpleName() + "_" + method.getName() + "_" + actionid;
|
||||
@@ -368,6 +371,27 @@ public abstract class SncpActionServlet extends SncpServlet {
|
||||
final java.lang.reflect.Type originalReturnType =
|
||||
TypeToken.getGenericType(method.getGenericReturnType(), serviceClass);
|
||||
|
||||
final Class[] paramClasses = method.getParameterTypes();
|
||||
java.lang.reflect.Type paramComposeBeanType0 = SncpRemoteAction.createParamComposeBeanType(
|
||||
serviceImplClass, method, actionid, originalParamTypes, paramClasses);
|
||||
if (paramComposeBeanType0 != null && paramComposeBeanType0 == originalParamTypes[0]) {
|
||||
paramComposeBeanType0 = null;
|
||||
}
|
||||
int handlerFuncIndex = -1;
|
||||
for (int i = 0; i < paramClasses.length; i++) { // 反序列化方法的每个参数
|
||||
if (CompletionHandler.class.isAssignableFrom(paramClasses[i])) {
|
||||
if (boolReturnTypeFuture) {
|
||||
throw new SncpException(method + " have both CompletionHandler and CompletableFuture");
|
||||
}
|
||||
if (handlerFuncIndex >= 0) {
|
||||
throw new SncpException(method + " have more than one CompletionHandler type parameter");
|
||||
}
|
||||
Sncp.checkAsyncModifier(paramClasses[i], method);
|
||||
handlerFuncIndex = i;
|
||||
}
|
||||
}
|
||||
final java.lang.reflect.Type paramComposeBeanType = paramComposeBeanType0;
|
||||
|
||||
if (newClazz == null) {
|
||||
// -------------------------------------------------------------
|
||||
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
|
||||
@@ -434,107 +458,193 @@ public abstract class SncpActionServlet extends SncpServlet {
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, requestName, "getReader", "()" + readerDesc, false);
|
||||
mv.visitVarInsn(ASTORE, 4);
|
||||
}
|
||||
int iconst = ICONST_1;
|
||||
int intconst = 1;
|
||||
int store = 5; // action的参数个数+2
|
||||
final Class[] paramClasses = method.getParameterTypes();
|
||||
int[][] codes = new int[paramClasses.length][2];
|
||||
int handlerFuncIndex = -1;
|
||||
for (int i = 0; i < paramClasses.length; i++) { // 反序列化方法的每个参数
|
||||
if (CompletionHandler.class.isAssignableFrom(paramClasses[i])) {
|
||||
if (boolReturnTypeFuture) {
|
||||
throw new SncpException(method + " have both CompletionHandler and CompletableFuture");
|
||||
if (paramComposeBeanType == null) {
|
||||
int iconst = ICONST_1;
|
||||
int intconst = 1;
|
||||
int store = 5; // action的参数个数+2
|
||||
int[][] codes = new int[paramClasses.length][2];
|
||||
for (int i = 0; i < paramClasses.length; i++) { // 反序列化方法的每个参数
|
||||
if (CompletionHandler.class.isAssignableFrom(paramClasses[i])) {
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL,
|
||||
responseName,
|
||||
"getParamAsyncHandler",
|
||||
"()Ljava/nio/channels/CompletionHandler;",
|
||||
false);
|
||||
mv.visitTypeInsn(
|
||||
CHECKCAST, paramClasses[i].getName().replace('.', '/'));
|
||||
mv.visitVarInsn(ASTORE, store);
|
||||
codes[i] = new int[] {ALOAD, store};
|
||||
store++;
|
||||
iconst++;
|
||||
intconst++;
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
mv.visitLdcInsn(Type.getType(Type.getDescriptor(CompletionHandler.class)));
|
||||
mv.visitVarInsn(ALOAD, 4);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
|
||||
mv.visitInsn(POP);
|
||||
continue;
|
||||
}
|
||||
if (handlerFuncIndex >= 0) {
|
||||
throw new SncpException(method + " have more than one CompletionHandler type parameter");
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "paramTypes", "[Ljava/lang/reflect/Type;");
|
||||
|
||||
if (intconst < 6) {
|
||||
mv.visitInsn(ICONST_0 + intconst);
|
||||
} else if (iconst <= Byte.MAX_VALUE) {
|
||||
mv.visitIntInsn(BIPUSH, intconst);
|
||||
} else if (iconst <= Short.MAX_VALUE) {
|
||||
mv.visitIntInsn(SIPUSH, intconst);
|
||||
} else {
|
||||
mv.visitLdcInsn(intconst);
|
||||
}
|
||||
Sncp.checkAsyncModifier(paramClasses[i], method);
|
||||
handlerFuncIndex = i;
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL,
|
||||
responseName,
|
||||
"getParamAsyncHandler",
|
||||
"()Ljava/nio/channels/CompletionHandler;",
|
||||
false);
|
||||
mv.visitTypeInsn(CHECKCAST, paramClasses[i].getName().replace('.', '/'));
|
||||
mv.visitVarInsn(ASTORE, store);
|
||||
codes[i] = new int[] {ALOAD, store};
|
||||
store++;
|
||||
mv.visitInsn(AALOAD);
|
||||
mv.visitVarInsn(ALOAD, 4);
|
||||
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
|
||||
int load = ALOAD;
|
||||
int v = 0;
|
||||
if (paramClasses[i].isPrimitive()) {
|
||||
int storecode = ISTORE;
|
||||
load = ILOAD;
|
||||
if (paramClasses[i] == long.class) {
|
||||
storecode = LSTORE;
|
||||
load = LLOAD;
|
||||
v = 1;
|
||||
} else if (paramClasses[i] == float.class) {
|
||||
storecode = FSTORE;
|
||||
load = FLOAD;
|
||||
v = 1;
|
||||
} else if (paramClasses[i] == double.class) {
|
||||
storecode = DSTORE;
|
||||
load = DLOAD;
|
||||
v = 1;
|
||||
}
|
||||
Class bigPrimitiveClass = TypeToken.primitiveToWrapper(paramClasses[i]);
|
||||
String bigPrimitiveName =
|
||||
bigPrimitiveClass.getName().replace('.', '/');
|
||||
try {
|
||||
Method pm = bigPrimitiveClass.getMethod(paramClasses[i].getSimpleName() + "Value");
|
||||
mv.visitTypeInsn(CHECKCAST, bigPrimitiveName);
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL,
|
||||
bigPrimitiveName,
|
||||
pm.getName(),
|
||||
Type.getMethodDescriptor(pm),
|
||||
false);
|
||||
} catch (Exception ex) {
|
||||
throw new SncpException(ex); // 不可能会发生
|
||||
}
|
||||
mv.visitVarInsn(storecode, store);
|
||||
} else {
|
||||
mv.visitTypeInsn(
|
||||
CHECKCAST, paramClasses[i].getName().replace('.', '/'));
|
||||
mv.visitVarInsn(ASTORE, store); //
|
||||
}
|
||||
codes[i] = new int[] {load, store};
|
||||
store += v;
|
||||
iconst++;
|
||||
intconst++;
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
mv.visitLdcInsn(Type.getType(Type.getDescriptor(CompletionHandler.class)));
|
||||
mv.visitVarInsn(ALOAD, 4);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
|
||||
mv.visitInsn(POP);
|
||||
continue;
|
||||
store++;
|
||||
}
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "paramTypes", "[Ljava/lang/reflect/Type;");
|
||||
{ // 调用service
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "service", "()" + serviceDesc, false);
|
||||
mv.visitTypeInsn(CHECKCAST, serviceImpTypeName);
|
||||
mv.visitVarInsn(ASTORE, store);
|
||||
|
||||
if (intconst < 6) {
|
||||
mv.visitInsn(ICONST_0 + intconst);
|
||||
} else if (iconst <= Byte.MAX_VALUE) {
|
||||
mv.visitIntInsn(BIPUSH, intconst);
|
||||
} else if (iconst <= Short.MAX_VALUE) {
|
||||
mv.visitIntInsn(SIPUSH, intconst);
|
||||
} else {
|
||||
mv.visitLdcInsn(intconst);
|
||||
}
|
||||
mv.visitInsn(AALOAD);
|
||||
mv.visitVarInsn(ALOAD, 4);
|
||||
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
|
||||
int load = ALOAD;
|
||||
int v = 0;
|
||||
if (paramClasses[i].isPrimitive()) {
|
||||
int storecode = ISTORE;
|
||||
load = ILOAD;
|
||||
if (paramClasses[i] == long.class) {
|
||||
storecode = LSTORE;
|
||||
load = LLOAD;
|
||||
v = 1;
|
||||
} else if (paramClasses[i] == float.class) {
|
||||
storecode = FSTORE;
|
||||
load = FLOAD;
|
||||
v = 1;
|
||||
} else if (paramClasses[i] == double.class) {
|
||||
storecode = DSTORE;
|
||||
load = DLOAD;
|
||||
v = 1;
|
||||
mv.visitVarInsn(ALOAD, store);
|
||||
for (int[] j : codes) {
|
||||
mv.visitVarInsn(j[0], j[1]);
|
||||
}
|
||||
Class bigPrimitiveClass = TypeToken.primitiveToWrapper(paramClasses[i]);
|
||||
String bigPrimitiveName = bigPrimitiveClass.getName().replace('.', '/');
|
||||
try {
|
||||
Method pm = bigPrimitiveClass.getMethod(paramClasses[i].getSimpleName() + "Value");
|
||||
mv.visitTypeInsn(CHECKCAST, bigPrimitiveName);
|
||||
mv.visitMethodInsn(
|
||||
serviceImplClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL,
|
||||
serviceImpTypeName,
|
||||
method.getName(),
|
||||
Type.getMethodDescriptor(method),
|
||||
serviceImplClass.isInterface());
|
||||
store++;
|
||||
}
|
||||
|
||||
if (method.getReturnType() != void.class) {
|
||||
final Class returnClass = method.getReturnType();
|
||||
if (returnClass.isPrimitive()) {
|
||||
Class bigClass = TypeToken.primitiveToWrapper(returnClass);
|
||||
try {
|
||||
Method vo = bigClass.getMethod("valueOf", returnClass);
|
||||
mv.visitMethodInsn(
|
||||
INVOKESTATIC,
|
||||
bigClass.getName().replace('.', '/'),
|
||||
vo.getName(),
|
||||
Type.getMethodDescriptor(vo),
|
||||
false);
|
||||
} catch (Exception ex) {
|
||||
throw new SncpException(ex); // 不可能会发生
|
||||
}
|
||||
}
|
||||
mv.visitVarInsn(ASTORE, store); // 11
|
||||
|
||||
if (boolReturnTypeFuture) { // 返回类型为Future
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "returnFutureType", reflectTypeDesc);
|
||||
mv.visitVarInsn(ALOAD, store);
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL, bigPrimitiveName, pm.getName(), Type.getMethodDescriptor(pm), false);
|
||||
} catch (Exception ex) {
|
||||
throw new SncpException(ex); // 不可能会发生
|
||||
INVOKEVIRTUAL,
|
||||
responseName,
|
||||
"finishFuture",
|
||||
"(" + reflectTypeDesc + futureDesc + ")V",
|
||||
false);
|
||||
} else if (handlerFuncIndex >= 0) { // 参数有CompletionHandler
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, responseName, "finishVoid", "()V", false);
|
||||
} else { // 普通对象
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "returnObjectType", reflectTypeDesc);
|
||||
mv.visitVarInsn(ALOAD, store);
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL,
|
||||
responseName,
|
||||
"finish",
|
||||
"(" + reflectTypeDesc + "Ljava/lang/Object;)V",
|
||||
false);
|
||||
}
|
||||
mv.visitVarInsn(storecode, store);
|
||||
} else {
|
||||
mv.visitTypeInsn(CHECKCAST, paramClasses[i].getName().replace('.', '/'));
|
||||
mv.visitVarInsn(ASTORE, store); //
|
||||
} else { // void返回类型
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, responseName, "finishVoid", "()V", false);
|
||||
}
|
||||
codes[i] = new int[] {load, store};
|
||||
store += v;
|
||||
iconst++;
|
||||
intconst++;
|
||||
store++;
|
||||
}
|
||||
{ // 调用service
|
||||
} else { // 动态生成的参数组合类
|
||||
Class paramComposeBeanClass = TypeToken.typeToClass(paramComposeBeanType);
|
||||
String paramComposeBeanName =
|
||||
paramComposeBeanClass.getName().replace('.', '/');
|
||||
mv.visitVarInsn(ALOAD, 3); // convert
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "paramComposeType", reflectTypeDesc);
|
||||
mv.visitVarInsn(ALOAD, 4); // reader
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
|
||||
mv.visitTypeInsn(CHECKCAST, paramComposeBeanName);
|
||||
mv.visitVarInsn(ASTORE, 5); // paramBean
|
||||
|
||||
// 给CompletionHandler参数赋值
|
||||
mv.visitVarInsn(ALOAD, 5);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, responseName, "getParamAsyncHandler", "()" + handlerDesc, false);
|
||||
mv.visitFieldInsn(PUTFIELD, paramComposeBeanName, "arg3", handlerDesc);
|
||||
|
||||
// 调用service()
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "service", "()" + serviceDesc, false);
|
||||
mv.visitTypeInsn(CHECKCAST, serviceImpTypeName);
|
||||
mv.visitVarInsn(ASTORE, store);
|
||||
mv.visitVarInsn(ASTORE, 6); // service
|
||||
|
||||
mv.visitVarInsn(ALOAD, store);
|
||||
for (int[] j : codes) {
|
||||
mv.visitVarInsn(j[0], j[1]);
|
||||
// 执行service方法
|
||||
mv.visitVarInsn(ALOAD, 6); // service
|
||||
for (int i = 1; i <= paramClasses.length; i++) {
|
||||
mv.visitVarInsn(ALOAD, 5); // paramBean
|
||||
mv.visitFieldInsn(
|
||||
GETFIELD, paramComposeBeanName, "arg" + i, Type.getDescriptor(paramClasses[i - 1]));
|
||||
}
|
||||
mv.visitMethodInsn(
|
||||
serviceImplClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL,
|
||||
@@ -542,58 +652,60 @@ public abstract class SncpActionServlet extends SncpServlet {
|
||||
method.getName(),
|
||||
Type.getMethodDescriptor(method),
|
||||
serviceImplClass.isInterface());
|
||||
store++;
|
||||
}
|
||||
if (method.getReturnType() != void.class) {
|
||||
final Class returnClass = method.getReturnType();
|
||||
if (returnClass.isPrimitive()) {
|
||||
Class bigClass = TypeToken.primitiveToWrapper(returnClass);
|
||||
try {
|
||||
Method vo = bigClass.getMethod("valueOf", returnClass);
|
||||
mv.visitMethodInsn(
|
||||
INVOKESTATIC,
|
||||
bigClass.getName().replace('.', '/'),
|
||||
vo.getName(),
|
||||
Type.getMethodDescriptor(vo),
|
||||
false);
|
||||
} catch (Exception ex) {
|
||||
throw new SncpException(ex); // 不可能会发生
|
||||
}
|
||||
}
|
||||
mv.visitVarInsn(ASTORE, store); // 11
|
||||
|
||||
if (boolReturnTypeFuture) { // 返回类型为Future
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "returnFutureResultType", "Ljava/lang/reflect/Type;");
|
||||
mv.visitVarInsn(ALOAD, store);
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL,
|
||||
responseName,
|
||||
"finishFuture",
|
||||
"(Ljava/lang/reflect/Type;Ljava/util/concurrent/Future;)V",
|
||||
false);
|
||||
} else if (handlerFuncIndex >= 0) { // 参数有CompletionHandler
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
// 返回
|
||||
if (method.getReturnType() != void.class) {
|
||||
final Class returnClass = method.getReturnType();
|
||||
if (returnClass.isPrimitive()) {
|
||||
Class bigClass = TypeToken.primitiveToWrapper(returnClass);
|
||||
try {
|
||||
Method vo = bigClass.getMethod("valueOf", returnClass);
|
||||
mv.visitMethodInsn(
|
||||
INVOKESTATIC,
|
||||
bigClass.getName().replace('.', '/'),
|
||||
vo.getName(),
|
||||
Type.getMethodDescriptor(vo),
|
||||
false);
|
||||
} catch (Exception ex) {
|
||||
throw new SncpException(ex); // 不可能会发生
|
||||
}
|
||||
}
|
||||
mv.visitVarInsn(ASTORE, 7); // returnObject
|
||||
|
||||
if (boolReturnTypeFuture) { // 返回类型为Future
|
||||
mv.visitVarInsn(ALOAD, 2); // response
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "returnFutureType", reflectTypeDesc);
|
||||
mv.visitVarInsn(ALOAD, 7); // returnObject
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL,
|
||||
responseName,
|
||||
"finishFuture",
|
||||
"(" + reflectTypeDesc + futureDesc + ")V",
|
||||
false);
|
||||
} else if (handlerFuncIndex >= 0) { // 参数有CompletionHandler
|
||||
mv.visitVarInsn(ALOAD, 2); // response
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, responseName, "finishVoid", "()V", false);
|
||||
} else { // 普通对象
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "returnObjectType", reflectTypeDesc);
|
||||
mv.visitVarInsn(ALOAD, 7); // returnObject
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL,
|
||||
responseName,
|
||||
"finish",
|
||||
"(" + reflectTypeDesc + "Ljava/lang/Object;)V",
|
||||
false);
|
||||
}
|
||||
} else { // void返回类型
|
||||
mv.visitVarInsn(ALOAD, 2); // response
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, responseName, "finishVoid", "()V", false);
|
||||
} else { // 普通对象
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "returnObjectType", "Ljava/lang/reflect/Type;");
|
||||
mv.visitVarInsn(ALOAD, store);
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL,
|
||||
responseName,
|
||||
"finish",
|
||||
"(Ljava/lang/reflect/Type;Ljava/lang/Object;)V",
|
||||
false);
|
||||
}
|
||||
} else { // void返回类型
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, responseName, "finishVoid", "()V", false);
|
||||
}
|
||||
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(8, store);
|
||||
mv.visitMaxs(8, 8);
|
||||
mv.visitEnd();
|
||||
}
|
||||
cw.visitEnd();
|
||||
|
||||
@@ -60,6 +60,9 @@ public final class SncpRemoteAction {
|
||||
// 参数数量为0: 值为null; 参数数量为1且参数类型为JavaBean: 值为第一个参数的类型; 其他情况: 动态生成的Object类
|
||||
protected final Type paramComposeBeanType;
|
||||
|
||||
// 只有paramComposeBeanType为动态生成的组合类时才有值;
|
||||
protected final Creator paramComposeBeanCreator;
|
||||
|
||||
protected final int paramHandlerIndex;
|
||||
|
||||
protected final int paramHandlerAttachIndex;
|
||||
@@ -72,9 +75,9 @@ public final class SncpRemoteAction {
|
||||
|
||||
protected final Class<? extends CompletionHandler> paramHandlerClass; // CompletionHandler参数的类型
|
||||
|
||||
protected final java.lang.reflect.Type paramHandlerResultType; // CompletionHandler.completed第一个参数的类型
|
||||
protected final java.lang.reflect.Type paramHandlerType; // CompletionHandler.completed第一个参数的类型
|
||||
|
||||
protected final java.lang.reflect.Type returnFutureResultType; // 返回结果的CompletableFuture的结果泛型类型
|
||||
protected final java.lang.reflect.Type returnFutureType; // 返回结果的CompletableFuture的结果泛型类型
|
||||
|
||||
protected final Class<? extends Future> returnFutureClass; // 返回结果的CompletableFuture类型
|
||||
|
||||
@@ -95,8 +98,10 @@ public final class SncpRemoteAction {
|
||||
this.returnObjectType = rt == void.class || rt == Void.class ? null : rt;
|
||||
this.paramTypes = TypeToken.getGenericType(method.getGenericParameterTypes(), serviceImplClass);
|
||||
this.paramClasses = method.getParameterTypes();
|
||||
this.paramComposeBeanType =
|
||||
createParamComposeBeanType(serviceImplClass, method, actionid, paramTypes, paramClasses);
|
||||
Type pt = createParamComposeBeanType(serviceImplClass, method, actionid, paramTypes, paramClasses);
|
||||
this.paramComposeBeanType = pt;
|
||||
this.paramComposeBeanCreator =
|
||||
(pt == null || pt == paramTypes[0]) ? null : Creator.create(TypeToken.typeToClass(pt), 1);
|
||||
this.method = method;
|
||||
Annotation[][] anns = method.getParameterAnnotations();
|
||||
int topicAddrIndex = -1;
|
||||
@@ -186,7 +191,7 @@ public final class SncpRemoteAction {
|
||||
this.paramAddressSourceIndex = sourceAddrIndex;
|
||||
this.paramHandlerIndex = handlerFuncIndex;
|
||||
this.paramHandlerClass = handlerFuncClass;
|
||||
this.paramHandlerResultType = handlerResultType;
|
||||
this.paramHandlerType = handlerResultType;
|
||||
this.paramHandlerAttachIndex = handlerAttachIndex;
|
||||
this.header = SncpHeader.create(
|
||||
sncpClient == null ? null : sncpClient.getClientSncpAddress(),
|
||||
@@ -209,7 +214,7 @@ public final class SncpRemoteAction {
|
||||
} else {
|
||||
throw new SncpException(serviceImplClass + " had unknown return genericType in " + method);
|
||||
}
|
||||
this.returnFutureResultType = returnType;
|
||||
this.returnFutureType = returnType;
|
||||
this.returnFutureClass = method.getReturnType().isAssignableFrom(CompletableFuture.class)
|
||||
? CompletableFuture.class
|
||||
: (Class) method.getReturnType();
|
||||
@@ -220,7 +225,7 @@ public final class SncpRemoteAction {
|
||||
throw new SncpException(serviceImplClass + " return must be CompletableFuture or subclass");
|
||||
}
|
||||
} else {
|
||||
this.returnFutureResultType = null;
|
||||
this.returnFutureType = null;
|
||||
this.returnFutureClass = null;
|
||||
this.returnFutureCreator = null;
|
||||
}
|
||||
@@ -247,7 +252,7 @@ public final class SncpRemoteAction {
|
||||
// 动态生成组合JavaBean类
|
||||
final Class serviceClass = resourceType.getClass();
|
||||
final String columnDesc = org.redkale.asm.Type.getDescriptor(ConvertColumn.class);
|
||||
final String newDynName = "org/redkaledyn/sncp/servlet/action/_DynSncpActionParamBean__"
|
||||
final String newDynName = "org/redkaledyn/sncp/servlet/action/_DynSncpActionParamBean_"
|
||||
+ resourceType.getSimpleName() + "_" + method.getName() + "_" + actionid;
|
||||
try {
|
||||
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
|
||||
@@ -278,7 +283,7 @@ public final class SncpRemoteAction {
|
||||
av.visitEnd();
|
||||
fv.visitEnd();
|
||||
}
|
||||
{ // 空参数构造函数
|
||||
{ // 空参数的构造函数
|
||||
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||
@@ -286,7 +291,7 @@ public final class SncpRemoteAction {
|
||||
mv.visitMaxs(1, 1);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{ // 带参数构造函数
|
||||
{ // 一个参数的构造函数
|
||||
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "([Ljava/lang/Object;)V", null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||
@@ -306,13 +311,16 @@ public final class SncpRemoteAction {
|
||||
cw.visitEnd();
|
||||
|
||||
byte[] bytes = cw.toByteArray();
|
||||
Class newClazz = new ClassLoader(serviceClass.getClassLoader()) {
|
||||
Class newClazz = new ClassLoader(Thread.currentThread().getContextClassLoader()) {
|
||||
public final Class<?> loadClass(String name, byte[] b) {
|
||||
return defineClass(name, b, 0, b.length);
|
||||
}
|
||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
||||
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
|
||||
RedkaleClassLoader.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
|
||||
Creator.load(newClazz);
|
||||
ProtobufFactory.root().loadDecoder(newClazz);
|
||||
ProtobufFactory.root().loadEncoder(newClazz);
|
||||
return newClazz;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ public class SncpRemoteInfo<S extends Service> {
|
||||
handler.completed(
|
||||
v == null
|
||||
? null
|
||||
: convert.convertFrom(action.paramHandlerResultType, v, 1, v.length - 1),
|
||||
: convert.convertFrom(action.paramHandlerType, v, 1, v.length - 1),
|
||||
attach);
|
||||
} else {
|
||||
handler.failed(t, attach);
|
||||
@@ -144,7 +144,7 @@ public class SncpRemoteInfo<S extends Service> {
|
||||
if (action.returnFutureClass == CompletableFuture.class) {
|
||||
// v,length-1为了读掉(byte)0
|
||||
return (T) future.thenApply(
|
||||
v -> v == null ? null : convert.convertFrom(action.returnFutureResultType, v, 1, v.length - 1));
|
||||
v -> v == null ? null : convert.convertFrom(action.returnFutureType, v, 1, v.length - 1));
|
||||
} else {
|
||||
final CompletableFuture returnFuture = action.returnFutureCreator.create();
|
||||
future.whenComplete((v, t) -> {
|
||||
@@ -153,7 +153,7 @@ public class SncpRemoteInfo<S extends Service> {
|
||||
returnFuture.complete(
|
||||
v == null
|
||||
? null
|
||||
: convert.convertFrom(action.returnFutureResultType, v, 1, v.length - 1));
|
||||
: convert.convertFrom(action.returnFutureType, v, 1, v.length - 1));
|
||||
} else {
|
||||
returnFuture.completeExceptionally(t);
|
||||
}
|
||||
@@ -256,8 +256,13 @@ public class SncpRemoteInfo<S extends Service> {
|
||||
byte[] body = null;
|
||||
if (myParamTypes.length > 0) { // 存在参数
|
||||
ProtobufWriter writer = convert.pollWriter();
|
||||
for (int i = 0; i < params.length; i++) { // service方法的参数
|
||||
convert.convertTo(writer, myParamTypes[i], params[i]);
|
||||
if (action.paramComposeBeanCreator != null) {
|
||||
Object paramBean = action.paramComposeBeanCreator.create(params);
|
||||
convert.convertTo(writer, action.paramComposeBeanType, paramBean);
|
||||
} else {
|
||||
for (int i = 0; i < params.length; i++) { // service方法的参数
|
||||
convert.convertTo(writer, myParamTypes[i], params[i]);
|
||||
}
|
||||
}
|
||||
body = writer.toByteArray().content();
|
||||
convert.offerWriter(writer);
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
*/
|
||||
package org.redkale.util;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.concurrent.*;
|
||||
@@ -360,6 +358,16 @@ public interface Creator<T> {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (constructor0 == null && paramCount == 1) {
|
||||
for (Constructor c : cs) {
|
||||
int cc = c.getParameterCount();
|
||||
if (cc == 1 && c.getParameterTypes()[0] == Object[].class) {
|
||||
constructor0 = c;
|
||||
constructorParameters0 = new SimpleEntry[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (constructor0 == null) { // 4、查找非private带ConstructorParameters的构造函数
|
||||
for (Constructor c : clazz.getDeclaredConstructors()) {
|
||||
@@ -439,12 +447,14 @@ public interface Creator<T> {
|
||||
int paramLen = constructorParameters.length;
|
||||
Asms.visitInsn(mv, paramLen);
|
||||
mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");
|
||||
|
||||
for (int i = 0; i < constructorParameters.length; i++) {
|
||||
final Class pt = constructorParameters[i].getValue();
|
||||
mv.visitInsn(DUP);
|
||||
Asms.visitInsn(mv, i);
|
||||
Asms.visitFieldInsn(mv, pt);
|
||||
if (constructorParameters[i] == null) {
|
||||
mv.visitLdcInsn(Type.getType("[Ljava/lang/Object;"));
|
||||
} else {
|
||||
Asms.visitFieldInsn(mv, constructorParameters[i].getValue());
|
||||
}
|
||||
mv.visitInsn(AASTORE);
|
||||
}
|
||||
mv.visitInsn(ARETURN);
|
||||
@@ -454,7 +464,7 @@ public interface Creator<T> {
|
||||
{ // create 方法
|
||||
mv = cw.visitMethod(
|
||||
ACC_PUBLIC + ACC_VARARGS, "create", "([Ljava/lang/Object;)L" + interName + ";", null, null);
|
||||
if (constructorParameters.length > 0) {
|
||||
if (constructorParameters.length > 0 && constructorParameters[0] != null) {
|
||||
av0 = mv.visitAnnotation(Type.getDescriptor(ConstructorParameters.class), true);
|
||||
AnnotationVisitor av1 = av0.visitArray("value");
|
||||
for (SimpleEntry<String, Class> n : constructorParameters) {
|
||||
@@ -463,81 +473,84 @@ public interface Creator<T> {
|
||||
av1.visitEnd();
|
||||
av0.visitEnd();
|
||||
}
|
||||
{ // 有Primitive数据类型且值为null的参数需要赋默认值
|
||||
for (int i = 0; i < constructorParameters.length; i++) {
|
||||
final Class pt = constructorParameters[i].getValue();
|
||||
if (!pt.isPrimitive()) {
|
||||
continue;
|
||||
}
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
Asms.visitInsn(mv, i);
|
||||
mv.visitInsn(AALOAD);
|
||||
Label lab = new Label();
|
||||
mv.visitJumpInsn(IFNONNULL, lab);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
Asms.visitInsn(mv, i);
|
||||
if (pt == int.class) {
|
||||
mv.visitInsn(ICONST_0);
|
||||
mv.visitMethodInsn(
|
||||
INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
|
||||
} else if (pt == long.class) {
|
||||
mv.visitInsn(LCONST_0);
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
|
||||
} else if (pt == boolean.class) {
|
||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "FALSE", "Ljava/lang/Boolean;");
|
||||
} else if (pt == short.class) {
|
||||
mv.visitInsn(ICONST_0);
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
|
||||
} else if (pt == float.class) {
|
||||
mv.visitInsn(FCONST_0);
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
|
||||
} else if (pt == byte.class) {
|
||||
mv.visitInsn(ICONST_0);
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
|
||||
} else if (pt == double.class) {
|
||||
mv.visitInsn(DCONST_0);
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
|
||||
} else if (pt == char.class) {
|
||||
mv.visitInsn(ICONST_0);
|
||||
mv.visitMethodInsn(
|
||||
INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
|
||||
}
|
||||
mv.visitInsn(AASTORE);
|
||||
mv.visitLabel(lab);
|
||||
// 有Primitive数据类型且值为null的参数需要赋默认值
|
||||
for (int i = 0; i < constructorParameters.length; i++) {
|
||||
if (constructorParameters[i] == null) {
|
||||
continue;
|
||||
}
|
||||
final Class pt = constructorParameters[i].getValue();
|
||||
if (!pt.isPrimitive()) {
|
||||
continue;
|
||||
}
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
Asms.visitInsn(mv, i);
|
||||
mv.visitInsn(AALOAD);
|
||||
Label lab = new Label();
|
||||
mv.visitJumpInsn(IFNONNULL, lab);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
Asms.visitInsn(mv, i);
|
||||
if (pt == int.class) {
|
||||
mv.visitInsn(ICONST_0);
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
|
||||
} else if (pt == long.class) {
|
||||
mv.visitInsn(LCONST_0);
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
|
||||
} else if (pt == boolean.class) {
|
||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "FALSE", "Ljava/lang/Boolean;");
|
||||
} else if (pt == short.class) {
|
||||
mv.visitInsn(ICONST_0);
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
|
||||
} else if (pt == float.class) {
|
||||
mv.visitInsn(FCONST_0);
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
|
||||
} else if (pt == byte.class) {
|
||||
mv.visitInsn(ICONST_0);
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
|
||||
} else if (pt == double.class) {
|
||||
mv.visitInsn(DCONST_0);
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
|
||||
} else if (pt == char.class) {
|
||||
mv.visitInsn(ICONST_0);
|
||||
mv.visitMethodInsn(
|
||||
INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
|
||||
}
|
||||
mv.visitInsn(AASTORE);
|
||||
mv.visitLabel(lab);
|
||||
}
|
||||
mv.visitTypeInsn(NEW, interName);
|
||||
mv.visitInsn(DUP);
|
||||
// ---------------------------------------
|
||||
{
|
||||
for (int i = 0; i < constructorParameters.length; i++) {
|
||||
for (int i = 0; i < constructorParameters.length; i++) {
|
||||
if (constructorParameters[i] == null) {
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
Asms.visitInsn(mv, i);
|
||||
mv.visitInsn(AALOAD);
|
||||
final Class ct = constructorParameters[i].getValue();
|
||||
if (ct.isPrimitive()) {
|
||||
final Class bigct = TypeToken.primitiveToWrapper(ct);
|
||||
mv.visitTypeInsn(CHECKCAST, bigct.getName().replace('.', '/'));
|
||||
try {
|
||||
Method pm = bigct.getMethod(ct.getSimpleName() + "Value");
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL,
|
||||
bigct.getName().replace('.', '/'),
|
||||
pm.getName(),
|
||||
Type.getMethodDescriptor(pm),
|
||||
false);
|
||||
} catch (Exception ex) {
|
||||
throw new RedkaleException(ex); // 不可能会发生
|
||||
}
|
||||
} else {
|
||||
mv.visitTypeInsn(CHECKCAST, ct.getName().replace('.', '/'));
|
||||
break;
|
||||
}
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
Asms.visitInsn(mv, i);
|
||||
mv.visitInsn(AALOAD);
|
||||
final Class ct = constructorParameters[i].getValue();
|
||||
if (ct.isPrimitive()) {
|
||||
final Class bigct = TypeToken.primitiveToWrapper(ct);
|
||||
mv.visitTypeInsn(CHECKCAST, bigct.getName().replace('.', '/'));
|
||||
try {
|
||||
Method pm = bigct.getMethod(ct.getSimpleName() + "Value");
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL,
|
||||
bigct.getName().replace('.', '/'),
|
||||
pm.getName(),
|
||||
Type.getMethodDescriptor(pm),
|
||||
false);
|
||||
} catch (Exception ex) {
|
||||
throw new RedkaleException(ex); // 不可能会发生
|
||||
}
|
||||
} else {
|
||||
mv.visitTypeInsn(CHECKCAST, ct.getName().replace('.', '/'));
|
||||
}
|
||||
}
|
||||
// ---------------------------------------
|
||||
mv.visitMethodInsn(INVOKESPECIAL, interName, "<init>", Type.getConstructorDescriptor(constructor), false);
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs((constructorParameters.length > 0 ? (constructorParameters.length + 3) : 2), 2);
|
||||
mv.visitMaxs(3, 2);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{ // 虚拟 create 方法
|
||||
@@ -555,52 +568,17 @@ public interface Creator<T> {
|
||||
mv.visitEnd();
|
||||
}
|
||||
cw.visitEnd();
|
||||
final byte[] bytes = cw.toByteArray();
|
||||
final boolean ispub = Modifier.isPublic(constructor.getModifiers());
|
||||
Class<?> resultClazz = null;
|
||||
if (loader instanceof URLClassLoader && !ispub) {
|
||||
try {
|
||||
final URLClassLoader urlLoader = (URLClassLoader) loader;
|
||||
final URL url = new URL(
|
||||
"memclass", "localhost", -1, "/" + newDynName.replace('/', '.') + "/", new URLStreamHandler() {
|
||||
@Override
|
||||
protected URLConnection openConnection(URL u) throws IOException {
|
||||
return new URLConnection(u) {
|
||||
@Override
|
||||
public void connect() throws IOException {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(bytes);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
Method addURLMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
|
||||
addURLMethod.setAccessible(true);
|
||||
addURLMethod.invoke(urlLoader, url);
|
||||
resultClazz = urlLoader.loadClass(newDynName.replace('/', '.'));
|
||||
} catch (Throwable t) { // 异常无需理会, 使用下一种loader方式
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (!ispub && resultClazz == null) {
|
||||
throw new RedkaleException(
|
||||
"[" + clazz + "] have no public or ConstructorParameters-Annotation constructor.");
|
||||
}
|
||||
byte[] bytes = cw.toByteArray();
|
||||
try {
|
||||
if (resultClazz == null) {
|
||||
resultClazz = new ClassLoader(loader) {
|
||||
public final Class<?> loadClass(String name, byte[] b) {
|
||||
return defineClass(name, b, 0, b.length);
|
||||
}
|
||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
||||
}
|
||||
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, resultClazz);
|
||||
RedkaleClassLoader.putReflectionDeclaredConstructors(resultClazz, newDynName.replace('/', '.'));
|
||||
return (Creator) resultClazz.getDeclaredConstructor().newInstance();
|
||||
Class newClazz = new ClassLoader(loader) {
|
||||
public final Class<?> loadClass(String name, byte[] b) {
|
||||
return defineClass(name, b, 0, b.length);
|
||||
}
|
||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
||||
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
|
||||
RedkaleClassLoader.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
|
||||
return (Creator) newClazz.getDeclaredConstructor().newInstance();
|
||||
} catch (Exception ex) {
|
||||
throw new RedkaleException(ex);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ public class SncpSleepTest {
|
||||
|
||||
@Test
|
||||
public void run() throws Exception {
|
||||
Creator.create(List.class);
|
||||
System.out.println("------------------- 并发调用 -----------------------------------");
|
||||
final Application application = Application.create(true);
|
||||
final ExecutorService workExecutor = WorkThread.createWorkExecutor(10, "Thread-Work-%s");
|
||||
|
||||
@@ -36,17 +36,17 @@ public class DynActionTestService_change extends SncpActionServlet {
|
||||
public void action(SncpRequest request, SncpResponse response) throws Throwable {
|
||||
Convert<Reader, Writer> convert = request.getConvert();
|
||||
Reader in = request.getReader();
|
||||
DynActionTestService_change_paramBean bean = convert.convertFrom(paramComposeBeanType, in);
|
||||
DynSncpActionParamBean_TestService_change bean = convert.convertFrom(paramComposeBeanType, in);
|
||||
TestService serviceObj = (TestService) service();
|
||||
Object rs = serviceObj.change(bean.arg1, bean.arg2, bean.arg3);
|
||||
response.finish(boolean.class, rs);
|
||||
}
|
||||
|
||||
public static class DynActionTestService_change_paramBean {
|
||||
public static class DynSncpActionParamBean_TestService_change {
|
||||
|
||||
public DynActionTestService_change_paramBean() {}
|
||||
public DynSncpActionParamBean_TestService_change() {}
|
||||
|
||||
public DynActionTestService_change_paramBean(Object[] params) {
|
||||
public DynSncpActionParamBean_TestService_change(Object[] params) {
|
||||
this.arg1 = (TestBean) params[0];
|
||||
this.arg2 = (String) params[1];
|
||||
this.arg3 = (int) params[2];
|
||||
|
||||
@@ -37,17 +37,17 @@ public class DynActionTestService_changeName extends SncpActionServlet {
|
||||
public void action(SncpRequest request, SncpResponse response) throws Throwable {
|
||||
Convert<Reader, Writer> convert = request.getConvert();
|
||||
Reader in = request.getReader();
|
||||
DynActionTestService_changeName_paramBean bean = convert.convertFrom(paramComposeBeanType, in);
|
||||
DynSncpActionParamBean_TestService_changeName bean = convert.convertFrom(paramComposeBeanType, in);
|
||||
TestService serviceObj = (TestService) service();
|
||||
CompletableFuture future = serviceObj.changeName(bean.arg1, bean.arg2, bean.arg3);
|
||||
response.finishFuture(paramHandlerResultType, future);
|
||||
response.finishFuture(paramHandlerType, future);
|
||||
}
|
||||
|
||||
public static class DynActionTestService_changeName_paramBean {
|
||||
public static class DynSncpActionParamBean_TestService_changeName {
|
||||
|
||||
public DynActionTestService_changeName_paramBean() {}
|
||||
public DynSncpActionParamBean_TestService_changeName() {}
|
||||
|
||||
public DynActionTestService_changeName_paramBean(Object[] params) {
|
||||
public DynSncpActionParamBean_TestService_changeName(Object[] params) {
|
||||
this.arg1 = (TestBean) params[0];
|
||||
this.arg2 = (String) params[1];
|
||||
this.arg3 = (int) params[2];
|
||||
|
||||
@@ -36,18 +36,18 @@ public class DynActionTestService_insert extends SncpActionServlet {
|
||||
public void action(SncpRequest request, SncpResponse response) throws Throwable {
|
||||
Convert<Reader, Writer> convert = request.getConvert();
|
||||
Reader in = request.getReader();
|
||||
DynActionTestService_insert_paramBean bean = convert.convertFrom(paramComposeBeanType, in);
|
||||
DynSncpActionParamBean_TestService_insert bean = convert.convertFrom(paramComposeBeanType, in);
|
||||
bean.arg0 = response.getParamAsyncHandler();
|
||||
TestService serviceObj = (TestService) service();
|
||||
serviceObj.insert(bean.arg0, bean.arg1, bean.arg2, bean.arg3);
|
||||
response.finishVoid();
|
||||
}
|
||||
|
||||
public static class DynActionTestService_insert_paramBean {
|
||||
public static class DynSncpActionParamBean_TestService_insert {
|
||||
|
||||
public DynActionTestService_insert_paramBean() {}
|
||||
public DynSncpActionParamBean_TestService_insert() {}
|
||||
|
||||
public DynActionTestService_insert_paramBean(Object[] params) {
|
||||
public DynSncpActionParamBean_TestService_insert(Object[] params) {
|
||||
this.arg0 = (BooleanHandler) params[0];
|
||||
this.arg1 = (TestBean) params[1];
|
||||
this.arg2 = (String) params[2];
|
||||
|
||||
@@ -37,18 +37,18 @@ public class DynActionTestService_update extends SncpActionServlet {
|
||||
public void action(SncpRequest request, SncpResponse response) throws Throwable {
|
||||
Convert<Reader, Writer> convert = request.getConvert();
|
||||
Reader in = request.getReader();
|
||||
DynActionTestService_update_paramBean bean = convert.convertFrom(paramComposeBeanType, in);
|
||||
DynSncpActionParamBean_TestService_update bean = convert.convertFrom(paramComposeBeanType, in);
|
||||
bean.arg3 = response.getParamAsyncHandler();
|
||||
TestService serviceObj = (TestService) service();
|
||||
serviceObj.update(bean.arg1, bean.arg2, bean.arg3, bean.arg4, bean.arg5, bean.arg6);
|
||||
response.finishVoid();
|
||||
}
|
||||
|
||||
public static class DynActionTestService_update_paramBean {
|
||||
public static class DynSncpActionParamBean_TestService_update {
|
||||
|
||||
public DynActionTestService_update_paramBean() {}
|
||||
public DynSncpActionParamBean_TestService_update() {}
|
||||
|
||||
public DynActionTestService_update_paramBean(Object[] params) {
|
||||
public DynSncpActionParamBean_TestService_update(Object[] params) {
|
||||
this.arg1 = (long) params[0];
|
||||
this.arg2 = (short) params[1];
|
||||
this.arg3 = (CompletionHandler) params[2];
|
||||
|
||||
@@ -31,6 +31,10 @@ public class CreatorRecord {
|
||||
|
||||
public CreatorRecord() {}
|
||||
|
||||
public CreatorRecord(Object[] arg) {
|
||||
System.out.println("creat CreatorRecord!");
|
||||
}
|
||||
|
||||
@ConstructorParameters({"id", "name", "lval", "tval", "bval", "sval", "cval", "fval", "dval"})
|
||||
public CreatorRecord(
|
||||
int id, String name, long lval, boolean tval, byte bval, short sval, char cval, float fval, double dval) {
|
||||
|
||||
@@ -19,6 +19,7 @@ public class CreatorTest {
|
||||
public static void main(String[] args) throws Throwable {
|
||||
CreatorTest test = new CreatorTest();
|
||||
test.run1();
|
||||
test.run2();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -35,4 +36,10 @@ public class CreatorTest {
|
||||
Assertions.assertEquals("ss", record.getName());
|
||||
Assertions.assertEquals(json, json2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void run2() throws Throwable {
|
||||
Creator<CreatorRecord> creator = Creator.create(CreatorRecord.class, 1);
|
||||
creator.create(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user