This commit is contained in:
redkale
2024-10-11 00:46:23 +08:00
parent 8ea63c5171
commit 335933a0f4
11 changed files with 410 additions and 295 deletions

View File

@@ -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&#60;Boolean, TestBean&#62; handler, TestBean bean, String name, int id);
*
* public CompletableFuture&#60;String&#62; changeName(TestBean bean, String name, int id);
* public CompletableFuture&#60;String&#62; changeName(TestBean bean, String name, int id);
*
* }
*
@@ -304,14 +304,14 @@ public abstract class SncpActionServlet extends SncpServlet {
* &#064;Override
* public void action(SncpRequest request, SncpResponse response) throws Throwable {
* Convert&#60;Reader, Writer&#62; 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();

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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");

View File

@@ -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];

View File

@@ -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];

View File

@@ -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];

View File

@@ -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];

View File

@@ -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) {

View File

@@ -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);
}
}