From 6db029263c84f87ac7c29f1ef1104670d6947229 Mon Sep 17 00:00:00 2001 From: redkale Date: Tue, 26 Dec 2023 00:16:45 +0800 Subject: [PATCH] MessageAsmMethodBoost --- .../java/org/redkale/asm/AsmMethodBoost.java | 16 +- src/main/java/org/redkale/asm/Asms.java | 19 ++ .../cache/spi/CacheAsmMethodBoost.java | 7 +- .../redkale/lock/spi/LockAsmMethodBoost.java | 5 +- .../org/redkale/mq/spi/DynForMessage.java | 3 + .../java/org/redkale/mq/spi/MessageAgent.java | 3 + .../redkale/mq/spi/MessageAsmMethodBoost.java | 221 +++++++++++++++++- .../redkale/mq/spi/MessageModuleEngine.java | 41 +++- src/main/java/org/redkale/net/http/Rest.java | 39 +--- src/main/java/org/redkale/net/sncp/Sncp.java | 15 +- .../org/redkale/net/sncp/SncpServlet.java | 7 +- .../org/redkale/util/RedkaleClassLoader.java | 27 +++ 12 files changed, 341 insertions(+), 62 deletions(-) diff --git a/src/main/java/org/redkale/asm/AsmMethodBoost.java b/src/main/java/org/redkale/asm/AsmMethodBoost.java index b8cefc49e..996a40ff7 100644 --- a/src/main/java/org/redkale/asm/AsmMethodBoost.java +++ b/src/main/java/org/redkale/asm/AsmMethodBoost.java @@ -86,6 +86,7 @@ public abstract class AsmMethodBoost { /** * 对方法进行动态加强处理 * + * @param classLoader ClassLoader * @param cw 动态字节码Writer * @param newDynName 动态新类名 * @param fieldPrefix 动态字段的前缀 @@ -95,16 +96,17 @@ public abstract class AsmMethodBoost { * * @return 下一个新的方法名,不做任何处理应返回参数newMethodName */ - public abstract String doMethod(ClassWriter cw, String newDynName, String fieldPrefix, - List> filterAnns, Method method, @Nullable String newMethodName); + public abstract String doMethod(ClassLoader classLoader, ClassWriter cw, String newDynName, + String fieldPrefix, List> filterAnns, Method method, @Nullable String newMethodName); /** 处理所有动态方法后调用 * + * @param classLoader ClassLoader * @param cw 动态字节码Writer * @param newDynName 动态新类名 * @param fieldPrefix 动态字段的前缀 */ - public void doAfterMethods(ClassWriter cw, String newDynName, String fieldPrefix) { + public void doAfterMethods(ClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) { } /** @@ -274,22 +276,22 @@ public abstract class AsmMethodBoost { } @Override - public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix, + public String doMethod(ClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix, List> filterAnns, Method method, String newMethodName) { String newName = newMethodName; for (AsmMethodBoost item : items) { if (item != null) { - newName = item.doMethod(cw, newDynName, fieldPrefix, filterAnns, method, newName); + newName = item.doMethod(classLoader, cw, newDynName, fieldPrefix, filterAnns, method, newName); } } return newName; } @Override - public void doAfterMethods(ClassWriter cw, String newDynName, String fieldPrefix) { + public void doAfterMethods(ClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) { for (AsmMethodBoost item : items) { if (item != null) { - item.doAfterMethods(cw, newDynName, fieldPrefix); + item.doAfterMethods(classLoader, cw, newDynName, fieldPrefix); } } } diff --git a/src/main/java/org/redkale/asm/Asms.java b/src/main/java/org/redkale/asm/Asms.java index 94731392e..f04c9999a 100644 --- a/src/main/java/org/redkale/asm/Asms.java +++ b/src/main/java/org/redkale/asm/Asms.java @@ -165,4 +165,23 @@ public final class Asms { } } + public static void visitPrimitiveVirtual(MethodVisitor mv, Class clazz) { + if (clazz == boolean.class) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false); + } else if (clazz == byte.class) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false); + } else if (clazz == short.class) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false); + } else if (clazz == char.class) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false); + } else if (clazz == int.class) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false); + } else if (clazz == float.class) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false); + } else if (clazz == long.class) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false); + } else if (clazz == double.class) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false); + } + } } diff --git a/src/main/java/org/redkale/cache/spi/CacheAsmMethodBoost.java b/src/main/java/org/redkale/cache/spi/CacheAsmMethodBoost.java index e163fc86e..0bca289ab 100644 --- a/src/main/java/org/redkale/cache/spi/CacheAsmMethodBoost.java +++ b/src/main/java/org/redkale/cache/spi/CacheAsmMethodBoost.java @@ -53,7 +53,8 @@ public class CacheAsmMethodBoost extends AsmMethodBoost { } @Override - public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix, List filterAnns, Method method, final String newMethodName) { + public String doMethod(ClassLoader classLoader, ClassWriter cw, + String newDynName, String fieldPrefix, List filterAnns, Method method, final String newMethodName) { Map actions = this.actionMap; if (actions == null) { actions = new LinkedHashMap<>(); @@ -134,8 +135,8 @@ public class CacheAsmMethodBoost extends AsmMethodBoost { } mv.visitInsn(AASTORE); } - - mv.visitMethodInsn(INVOKEVIRTUAL, CacheAction.class.getName().replace('.', '/'), "get", "(Lorg/redkale/util/ThrowSupplier;[Ljava/lang/Object;)Ljava/lang/Object;", false); + String throwFuncDesc = Type.getDescriptor(ThrowSupplier.class); + mv.visitMethodInsn(INVOKEVIRTUAL, CacheAction.class.getName().replace('.', '/'), "get", "(" + throwFuncDesc + "[Ljava/lang/Object;)Ljava/lang/Object;", false); mv.visitTypeInsn(CHECKCAST, method.getReturnType().getName().replace('.', '/')); mv.visitInsn(ARETURN); Label l2 = new Label(); diff --git a/src/main/java/org/redkale/lock/spi/LockAsmMethodBoost.java b/src/main/java/org/redkale/lock/spi/LockAsmMethodBoost.java index a7b12b006..ff06ea2e1 100644 --- a/src/main/java/org/redkale/lock/spi/LockAsmMethodBoost.java +++ b/src/main/java/org/redkale/lock/spi/LockAsmMethodBoost.java @@ -38,7 +38,8 @@ public class LockAsmMethodBoost extends AsmMethodBoost { } @Override - public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix, List filterAnns, Method method, final String newMethodName) { + public String doMethod(ClassLoader classLoader, ClassWriter cw, + String newDynName, String fieldPrefix, List filterAnns, Method method, final String newMethodName) { Locked locked = method.getAnnotation(Locked.class); if (locked == null) { return newMethodName; @@ -77,7 +78,7 @@ public class LockAsmMethodBoost extends AsmMethodBoost { } @Override - public void doAfterMethods(ClassWriter cw, String newDynName, String fieldPrefix) { + public void doAfterMethods(ClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) { //do nothing } diff --git a/src/main/java/org/redkale/mq/spi/DynForMessage.java b/src/main/java/org/redkale/mq/spi/DynForMessage.java index cbf0ee5ce..8f663b391 100644 --- a/src/main/java/org/redkale/mq/spi/DynForMessage.java +++ b/src/main/java/org/redkale/mq/spi/DynForMessage.java @@ -5,6 +5,7 @@ package org.redkale.mq.spi; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.TYPE; +import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; @@ -16,6 +17,7 @@ import org.redkale.mq.MessageConsumer; * * @author zhangjx */ +@Inherited @Documented @Target({TYPE}) @Retention(RUNTIME) @@ -24,6 +26,7 @@ public @interface DynForMessage { Class value(); + @Inherited @Documented @Target({TYPE}) @Retention(RUNTIME) diff --git a/src/main/java/org/redkale/mq/spi/MessageAgent.java b/src/main/java/org/redkale/mq/spi/MessageAgent.java index 474da011c..66e11eb66 100644 --- a/src/main/java/org/redkale/mq/spi/MessageAgent.java +++ b/src/main/java/org/redkale/mq/spi/MessageAgent.java @@ -167,6 +167,9 @@ public abstract class MessageAgent implements MessageManager { if (loginfo.length() > 0) { logger.log(Level.INFO, loginfo.toString()); } + if (application.isCompileMode()) { + return; + } //----------------- MessageClient ----------------- if (this.httpRpcClient != null || !this.httpMessageClient.isEmpty()) { this.httpMessageClient.putMessageRespProcessor(); diff --git a/src/main/java/org/redkale/mq/spi/MessageAsmMethodBoost.java b/src/main/java/org/redkale/mq/spi/MessageAsmMethodBoost.java index 8e087e180..00ac96350 100644 --- a/src/main/java/org/redkale/mq/spi/MessageAsmMethodBoost.java +++ b/src/main/java/org/redkale/mq/spi/MessageAsmMethodBoost.java @@ -7,14 +7,50 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import org.redkale.asm.AnnotationVisitor; +import org.redkale.asm.AsmMethodBean; import org.redkale.asm.AsmMethodBoost; +import org.redkale.asm.Asms; import org.redkale.asm.ClassWriter; +import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES; +import org.redkale.asm.FieldVisitor; +import org.redkale.asm.Label; +import org.redkale.asm.MethodVisitor; +import org.redkale.asm.Opcodes; +import static org.redkale.asm.Opcodes.ACC_BRIDGE; +import static org.redkale.asm.Opcodes.ACC_PRIVATE; +import static org.redkale.asm.Opcodes.ACC_PUBLIC; +import static org.redkale.asm.Opcodes.ACC_STATIC; +import static org.redkale.asm.Opcodes.ACC_SUPER; +import static org.redkale.asm.Opcodes.ACC_SYNTHETIC; +import static org.redkale.asm.Opcodes.ALOAD; +import static org.redkale.asm.Opcodes.ASTORE; +import static org.redkale.asm.Opcodes.ATHROW; +import static org.redkale.asm.Opcodes.CHECKCAST; +import static org.redkale.asm.Opcodes.DUP; +import static org.redkale.asm.Opcodes.GETFIELD; +import static org.redkale.asm.Opcodes.GOTO; +import static org.redkale.asm.Opcodes.INVOKESPECIAL; +import static org.redkale.asm.Opcodes.INVOKEVIRTUAL; +import static org.redkale.asm.Opcodes.NEW; +import static org.redkale.asm.Opcodes.POP; +import static org.redkale.asm.Opcodes.PUTFIELD; +import static org.redkale.asm.Opcodes.RETURN; +import static org.redkale.asm.Opcodes.V11; import org.redkale.convert.ConvertFactory; import org.redkale.inject.ResourceFactory; import org.redkale.mq.MessageConext; +import org.redkale.mq.MessageConsumer; import org.redkale.mq.Messaged; +import org.redkale.mq.ResourceConsumer; +import org.redkale.util.RedkaleClassLoader; import org.redkale.util.RedkaleException; +import org.redkale.util.TypeToken; +import org.redkale.util.Utility; /** * @@ -24,8 +60,19 @@ public class MessageAsmMethodBoost extends AsmMethodBoost { private static final List> FILTER_ANN = List.of(Messaged.class); - public MessageAsmMethodBoost(boolean remote, Class serviceType) { + private final AtomicInteger index = new AtomicInteger(); + + private final MessageModuleEngine messageEngine; + + private Map methodBeans; + + private RedkaleClassLoader.DynBytesClassLoader newLoader; + + private List> consumers; + + public MessageAsmMethodBoost(boolean remote, Class serviceType, MessageModuleEngine messageEngine) { super(remote, serviceType); + this.messageEngine = messageEngine; } @Override @@ -34,7 +81,8 @@ public class MessageAsmMethodBoost extends AsmMethodBoost { } @Override - public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix, List filterAnns, Method method, String newMethodName) { + public String doMethod(ClassLoader classLoader, ClassWriter cw, + String newDynName, String fieldPrefix, List filterAnns, Method method, String newMethodName) { if (serviceType.getAnnotation(DynForMessage.class) != null) { return newMethodName; } @@ -72,11 +120,180 @@ public class MessageAsmMethodBoost extends AsmMethodBoost { } ConvertFactory factory = ConvertFactory.findConvert(messaged.convertType()).getFactory(); factory.loadDecoder(messageType); + if (newLoader == null) { + newLoader = new RedkaleClassLoader.DynBytesClassLoader(classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader); + } + createInnerConsumer(cw, method, paramKind, TypeToken.typeToClass(messageType), messaged, newDynName, newMethodName); return newMethodName; } + //paramKind: 1:单个MessageType; 2: MessageConext & MessageType; 3: MessageType & MessageConext; + private void createInnerConsumer(ClassWriter parentCW, Method method, int paramKind, + Class msgType, Messaged messaged, String newDynName, String newMethodName) { + final String newDynDesc = "L" + newDynName + ";"; + final String innerClassName = "Dyn" + MessageConsumer.class.getSimpleName() + index.incrementAndGet(); + final String innerFullName = newDynName + "$" + innerClassName; + final String msgTypeDesc = org.redkale.asm.Type.getDescriptor(TypeToken.primitiveToWrapper(msgType)); + final String messageConsumerName = MessageConsumer.class.getName().replace('.', '/'); + final String messageConsumerDesc = org.redkale.asm.Type.getDescriptor(MessageConsumer.class); + final String messageConextDesc = org.redkale.asm.Type.getDescriptor(MessageConext.class); + final boolean throwFlag = Utility.contains(method.getExceptionTypes(), e -> !RuntimeException.class.isAssignableFrom(e)); + + if (methodBeans == null) { + methodBeans = AsmMethodBoost.getMethodBeans(serviceType); + } + AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method); + String genericMsgTypeDesc = msgTypeDesc; + if (!msgType.isPrimitive()) { + String methodSignature = methodBean.getSignature().replace(messageConextDesc, ""); + genericMsgTypeDesc = methodSignature.substring(1, methodSignature.lastIndexOf(')')); //获取()中的值 + } + + parentCW.visitInnerClass(innerFullName, newDynName, innerClassName, ACC_PUBLIC + ACC_STATIC); + + MethodVisitor mv; + ClassWriter cw = new ClassWriter(COMPUTE_FRAMES); + // + cw.visit(V11, ACC_PUBLIC + ACC_SUPER, innerFullName, "Ljava/lang/Object;" + messageConsumerDesc.replace(";", "<" + genericMsgTypeDesc + ">;"), + "java/lang/Object", new String[]{messageConsumerName}); + { + AnnotationVisitor av = cw.visitAnnotation(org.redkale.asm.Type.getDescriptor(ResourceConsumer.class), true); + Asms.visitAnnotation(av, messaged); + av.visitEnd(); + } + cw.visitInnerClass(innerFullName, newDynName, innerClassName, ACC_PUBLIC + ACC_STATIC); + { + FieldVisitor fv = cw.visitField(ACC_PRIVATE, "service", newDynDesc, null, null); + fv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC, "", "(" + newDynDesc + ")V", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitFieldInsn(PUTFIELD, innerFullName, "service", newDynDesc); + Label l2 = new Label(); + mv.visitLabel(l2); + mv.visitInsn(RETURN); + Label l3 = new Label(); + mv.visitLabel(l3); + mv.visitLocalVariable("this", "L" + innerFullName + ";", null, l0, l3, 0); + mv.visitLocalVariable("service", newDynDesc, null, l0, l3, 1); + mv.visitMaxs(2, 2); + mv.visitEnd(); + } + { + String methodName = newMethodName == null ? method.getName() : newMethodName; + mv = cw.visitMethod(ACC_PUBLIC, "onMessage", "(" + messageConextDesc + msgTypeDesc + ")V", + msgTypeDesc.equals(genericMsgTypeDesc) ? null : ("(" + messageConextDesc + genericMsgTypeDesc + ")V"), null); + Label l0 = new Label(); + Label l1 = new Label(); + Label l2 = new Label(); + if (throwFlag) { + mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Throwable"); + mv.visitLabel(l0); + } + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, innerFullName, "service", newDynDesc); + if (paramKind == 1) { //1: 单个MessageType; + mv.visitVarInsn(ALOAD, 2); + Asms.visitPrimitiveVirtual(mv, msgType); + } else if (paramKind == 2) { //2: MessageConext & MessageType; + mv.visitVarInsn(ALOAD, 1); + mv.visitVarInsn(ALOAD, 2); + Asms.visitPrimitiveVirtual(mv, msgType); + } else { //3: MessageType & MessageConext; + mv.visitVarInsn(ALOAD, 2); + Asms.visitPrimitiveVirtual(mv, msgType); + mv.visitVarInsn(ALOAD, 1); + } + mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, methodName, org.redkale.asm.Type.getMethodDescriptor(method), false); + if (method.getReturnType() != void.class) { + mv.visitInsn(POP); + } + mv.visitLabel(l1); + Label l3 = null, l4 = null; + if (throwFlag) { + l3 = new Label(); + mv.visitJumpInsn(GOTO, l3); + mv.visitLabel(l2); + mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/Throwable"}); + mv.visitVarInsn(ASTORE, 3); + l4 = new Label(); + mv.visitLabel(l4); + mv.visitTypeInsn(NEW, "java/lang/RuntimeException"); + mv.visitInsn(DUP); + mv.visitVarInsn(ALOAD, 3); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "", "(Ljava/lang/Throwable;)V", false); + mv.visitInsn(ATHROW); + mv.visitLabel(l3); + mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); + } + mv.visitInsn(RETURN); + Label l5 = new Label(); + mv.visitLabel(l5); + mv.visitLocalVariable("this", "L" + innerFullName + ";", null, l0, l5, 0); + mv.visitLocalVariable("context", messageConextDesc, null, l0, l5, 1); + mv.visitLocalVariable("message", msgTypeDesc, msgTypeDesc.equals(genericMsgTypeDesc) ? null : genericMsgTypeDesc, l0, l5, 2); + if (throwFlag) { + mv.visitLocalVariable("e", "Ljava/lang/Throwable;", null, l4, l3, 3); + } + mv.visitMaxs(4, 4); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "onMessage", "(" + messageConextDesc + "Ljava/lang/Object;)V", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitVarInsn(ALOAD, 2); + mv.visitTypeInsn(CHECKCAST, "java/lang/String"); + mv.visitMethodInsn(INVOKEVIRTUAL, innerFullName, "onMessage", "(" + messageConextDesc + msgTypeDesc + ")V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(3, 3); + mv.visitEnd(); + } + cw.visitEnd(); + + byte[] bytes = cw.toByteArray(); + Class cz = newLoader.loadClass((innerFullName).replace('/', '.'), bytes); + if (consumers == null) { + consumers = new ArrayList<>(); + } + consumers.add(cz); + RedkaleClassLoader.putDynClass((innerFullName).replace('/', '.'), bytes, cz); + } + @Override public void doInstance(ResourceFactory resourceFactory, Object service) { + DynForMessage[] dyns = service.getClass().getAnnotationsByType(DynForMessage.class); + if (dyns.length < 1) { + return; + } + try { + if (Utility.isNotEmpty(consumers)) { + for (Class clazz : consumers) { + MessageConsumer consumer = (MessageConsumer) clazz.getConstructors()[0].newInstance(service); + messageEngine.addMessageConsumer(consumer); + } + } else { + for (DynForMessage item : dyns) { + Class clazz = item.value(); + MessageConsumer consumer = (MessageConsumer) clazz.getConstructors()[0].newInstance(service); + messageEngine.addMessageConsumer(consumer); + } + } + } catch (Exception e) { + throw new RedkaleException(e); + } } } diff --git a/src/main/java/org/redkale/mq/spi/MessageModuleEngine.java b/src/main/java/org/redkale/mq/spi/MessageModuleEngine.java index 63f64fb10..78c4ed3b8 100644 --- a/src/main/java/org/redkale/mq/spi/MessageModuleEngine.java +++ b/src/main/java/org/redkale/mq/spi/MessageModuleEngine.java @@ -17,6 +17,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.logging.Level; +import org.redkale.asm.AsmMethodBoost; import org.redkale.boot.Application; import org.redkale.boot.ClassFilter; import org.redkale.boot.ModuleEngine; @@ -59,6 +60,23 @@ public class MessageModuleEngine extends ModuleEngine { super(application); } + /** + * 动态扩展类的方法 + * + * @param remote 是否远程模式 + * @param serviceClass 类 + * + * @return 方法动态扩展器 + */ + public AsmMethodBoost createAsmMethodBoost(boolean remote, Class serviceClass) { + return new MessageAsmMethodBoost(remote, serviceClass, this); + } + + void addMessageConsumer(MessageConsumer consumer) { + String agentName = consumer.getClass().getAnnotation(ResourceConsumer.class).mq(); + agentConsumers.computeIfAbsent(agentName, v -> new CopyOnWriteArrayList<>()).add(consumer); + } + /** * 判断模块的配置项合并策略, 返回null表示模块不识别此配置项 * @@ -205,10 +223,17 @@ public class MessageModuleEngine extends ModuleEngine { } long s = System.currentTimeMillis(); for (MessageAgent agent : this.messageAgents) { - this.resourceFactory.inject(agent); - agent.init(agent.getConfig()); - this.resourceFactory.register(agent.getName(), MessageManager.class, agent); - this.resourceFactory.register(agent.getName(), MessageAgent.class, agent); + String agentName = agent.getConfig().getValue("name", ""); + if (!application.isCompileMode()) { + this.resourceFactory.inject(agent); + agent.init(agent.getConfig()); + agentName = agent.getName(); + } else { + agent.name = agentName; + agent.application = application; + } + this.resourceFactory.register(agentName, MessageManager.class, agent); + this.resourceFactory.register(agentName, MessageAgent.class, agent); } logger.info("MessageAgent init in " + (System.currentTimeMillis() - s) + " ms"); } @@ -409,7 +434,9 @@ public class MessageModuleEngine extends ModuleEngine { long s = System.currentTimeMillis(); for (MessageAgent agent : this.messageAgents) { names.add(agent.getName()); - agent.stop(); + if (!application.isCompileMode()) { + agent.stop(); + } } logger.info("MessageAgent(names=" + JsonConvert.root().convertTo(names) + ") stop in " + (System.currentTimeMillis() - s) + " ms"); } @@ -427,7 +454,9 @@ public class MessageModuleEngine extends ModuleEngine { long s = System.currentTimeMillis(); for (MessageAgent agent : this.messageAgents) { names.add(agent.getName()); - agent.destroy(agent.getConfig()); + if (!application.isCompileMode()) { + agent.destroy(agent.getConfig()); + } } logger.info("MessageAgent(names=" + JsonConvert.root().convertTo(names) + ") destroy in " + (System.currentTimeMillis() - s) + " ms"); } diff --git a/src/main/java/org/redkale/net/http/Rest.java b/src/main/java/org/redkale/net/http/Rest.java index c396e28d6..e495b5b2e 100644 --- a/src/main/java/org/redkale/net/http/Rest.java +++ b/src/main/java/org/redkale/net/http/Rest.java @@ -5,7 +5,6 @@ */ package org.redkale.net.http; -import org.redkale.mq.spi.MessageAgent; import java.io.*; import java.lang.annotation.*; import static java.lang.annotation.ElementType.TYPE; @@ -24,12 +23,13 @@ import org.redkale.asm.Type; import org.redkale.convert.*; import org.redkale.convert.json.*; import org.redkale.inject.ResourceFactory; -import org.redkale.mq.*; +import org.redkale.mq.spi.MessageAgent; import org.redkale.net.*; import org.redkale.net.sncp.Sncp; import org.redkale.service.*; import org.redkale.source.Flipper; import org.redkale.util.*; +import org.redkale.util.RedkaleClassLoader.DynBytesClassLoader; import static org.redkale.util.Utility.isEmpty; /** @@ -612,7 +612,7 @@ public final class Rest { mv.visitEnd(); } - RestClassLoader newLoader = new RestClassLoader(loader); + DynBytesClassLoader newLoader = new DynBytesClassLoader(loader); Map msgclassToAnnotations = new HashMap<>(); for (int i = 0; i < messageMethods.size(); i++) { // _DyncXXXWebSocketMessage 子消息List final Method method = messageMethods.get(i); @@ -1608,6 +1608,7 @@ public final class Rest { final String defModuleName = getWebModuleNameLowerCase(serviceType); final String bigModuleName = getWebModuleName(serviceType); final String catalog = controller == null ? "" : controller.catalog(); + final String httpDesc = Type.getDescriptor(HttpServlet.class); if (!checkName(catalog)) { throw new RestException(serviceType.getName() + " have illegal " + RestService.class.getSimpleName() + ".catalog, only 0-9 a-z A-Z _ cannot begin 0-9"); } @@ -1725,7 +1726,7 @@ public final class Rest { return null; //没有可HttpMapping的方法 } Collections.sort(entrys); - RestClassLoader newLoader = new RestClassLoader(loader); + DynBytesClassLoader newLoader = new DynBytesClassLoader(loader); final int moduleid = controller == null ? 0 : controller.moduleid(); { //注入 @WebServlet 注解 String urlpath = ""; @@ -3391,7 +3392,7 @@ public final class Rest { mv.visitInsn(DUP); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, newDynName + "$" + entry.newActionClassName, "", "(L" + newDynName + ";)V", false); - mv.visitMethodInsn(INVOKESPECIAL, actionEntryName, "", "(IILjava/lang/String;[Ljava/lang/String;Ljava/lang/reflect/Method;ZZILorg/redkale/net/http/HttpServlet;)V", false); + mv.visitMethodInsn(INVOKESPECIAL, actionEntryName, "", "(IILjava/lang/String;[Ljava/lang/String;Ljava/lang/reflect/Method;ZZI" + httpDesc + ")V", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/HashMap", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", false); mv.visitInsn(POP); } @@ -3477,7 +3478,7 @@ public final class Rest { try { RedkaleClassLoader.putDynClass(n, bs, newLoader.findClass(n)); RedkaleClassLoader.putReflectionClass(n); - } catch (ClassNotFoundException e) { + } catch (Exception e) { throw new RestException(e); } }); @@ -3626,32 +3627,6 @@ public final class Rest { return true; } - private static class RestClassLoader extends ClassLoader { - - private final Map classes = new HashMap<>(); - - public RestClassLoader(ClassLoader parent) { - super(parent); - } - - @Override - protected Class findClass(String name) throws ClassNotFoundException { - byte[] classData = classes.get(name); - if (classData == null) { - return super.findClass(name); - } - return super.defineClass(name, classData, 0, classData.length); - } - - public final Class loadClass(String name, byte[] b) { - return defineClass(name, b, 0, b.length); - } - - public final void addClass(String name, byte[] b) { - classes.put(name, b); - } - } - private static class MappingEntry implements Comparable { private static final RestMapping DEFAULT__MAPPING; diff --git a/src/main/java/org/redkale/net/sncp/Sncp.java b/src/main/java/org/redkale/net/sncp/Sncp.java index 2f7209f7f..7a765c599 100644 --- a/src/main/java/org/redkale/net/sncp/Sncp.java +++ b/src/main/java/org/redkale/net/sncp/Sncp.java @@ -552,8 +552,8 @@ public abstract class Sncp { mv.visitEnd(); } if (methodBoost != null) { - createNewMethods(serviceImplClass, methodBoost, new HashSet<>(), cw, newDynName, supDynName); - methodBoost.doAfterMethods(cw, newDynName, FIELDPREFIX); + createNewMethods(classLoader, serviceImplClass, methodBoost, new HashSet<>(), cw, newDynName, supDynName); + methodBoost.doAfterMethods(classLoader, cw, newDynName, FIELDPREFIX); } cw.visitEnd(); byte[] bytes = cw.toByteArray(); @@ -581,7 +581,8 @@ public abstract class Sncp { return createLocalService(null, "", serviceImplClass, null, resourceFactory, null, null, null, null, null); } - private static void createNewMethods(Class clazz, final AsmMethodBoost methodBoost, Set methodKeys, ClassWriter cw, String newDynName, String supDynName) { + private static void createNewMethods(ClassLoader classLoader, Class clazz, + final AsmMethodBoost methodBoost, Set methodKeys, ClassWriter cw, String newDynName, String supDynName) { if (methodBoost == null) { return; } @@ -596,7 +597,7 @@ public abstract class Sncp { } methodKeys.add(mk); List> filterAnns = methodBoost.filterMethodAnnotations(method); - String newMethodName = methodBoost.doMethod(cw, newDynName, FIELDPREFIX, filterAnns, method, null); + String newMethodName = methodBoost.doMethod(classLoader, cw, newDynName, FIELDPREFIX, filterAnns, method, null); if (newMethodName != null) { String desc = Type.getMethodDescriptor(method); AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method); @@ -995,7 +996,7 @@ public abstract class Sncp { String newMethodName = null; if (methodBoost != null) { List> filterAnns = methodBoost.filterMethodAnnotations(method); - newMethodName = methodBoost.doMethod(cw, newDynName, FIELDPREFIX, filterAnns, method, null); + newMethodName = methodBoost.doMethod(classLoader, cw, newDynName, FIELDPREFIX, filterAnns, method, null); } if (newMethodName != null) { acc = ACC_PRIVATE; @@ -1097,8 +1098,8 @@ public abstract class Sncp { mv.visitEnd(); } if (methodBoost != null) { - createNewMethods(serviceTypeOrImplClass, methodBoost, methodKeys, cw, newDynName, supDynName); - methodBoost.doAfterMethods(cw, newDynName, FIELDPREFIX); + createNewMethods(classLoader, serviceTypeOrImplClass, methodBoost, methodKeys, cw, newDynName, supDynName); + methodBoost.doAfterMethods(classLoader, cw, newDynName, FIELDPREFIX); } cw.visitEnd(); byte[] bytes = cw.toByteArray(); diff --git a/src/main/java/org/redkale/net/sncp/SncpServlet.java b/src/main/java/org/redkale/net/sncp/SncpServlet.java index 179f64440..dbcebf852 100644 --- a/src/main/java/org/redkale/net/sncp/SncpServlet.java +++ b/src/main/java/org/redkale/net/sncp/SncpServlet.java @@ -467,6 +467,7 @@ public class SncpServlet extends Servlet final String responseName = SncpResponse.class.getName().replace('.', '/'); final String requestDesc = Type.getDescriptor(SncpRequest.class); final String responseDesc = Type.getDescriptor(SncpResponse.class); + final String serviceDesc = Type.getDescriptor(Service.class); final boolean boolReturnTypeFuture = Future.class.isAssignableFrom(method.getReturnType()); final String newDynName = "org/redkaledyn/sncp/servlet/action/_DynSncpActionServlet__" + resourceType.getSimpleName() + "_" + method.getName() + "_" + actionid; @@ -488,7 +489,7 @@ public class SncpServlet extends Servlet cw.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null); { - mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "", "(Ljava/lang/String;Ljava/lang/Class;Lorg/redkale/service/Service;" + uint128Desc + uint128Desc + "Ljava/lang/reflect/Method;)V", null, null)); + mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "", "(Ljava/lang/String;Ljava/lang/Class;" + serviceDesc + uint128Desc + uint128Desc + "Ljava/lang/reflect/Method;)V", null, null)); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); @@ -496,7 +497,7 @@ public class SncpServlet extends Servlet mv.visitVarInsn(ALOAD, 4); mv.visitVarInsn(ALOAD, 5); mv.visitVarInsn(ALOAD, 6); - mv.visitMethodInsn(INVOKESPECIAL, supDynName, "", "(Ljava/lang/String;Ljava/lang/Class;Lorg/redkale/service/Service;" + uint128Desc + uint128Desc + "Ljava/lang/reflect/Method;)V", false); + mv.visitMethodInsn(INVOKESPECIAL, supDynName, "", "(Ljava/lang/String;Ljava/lang/Class;" + serviceDesc + uint128Desc + uint128Desc + "Ljava/lang/reflect/Method;)V", false); mv.visitInsn(RETURN); mv.visitMaxs(7, 7); mv.visitEnd(); @@ -608,7 +609,7 @@ public class SncpServlet extends Servlet } { //调用service mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "service", "()Lorg/redkale/service/Service;", false); + mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "service", "()" + serviceDesc, false); mv.visitTypeInsn(CHECKCAST, serviceImpTypeName); mv.visitVarInsn(ASTORE, store); diff --git a/src/main/java/org/redkale/util/RedkaleClassLoader.java b/src/main/java/org/redkale/util/RedkaleClassLoader.java index d6f06a843..f7665ad6e 100644 --- a/src/main/java/org/redkale/util/RedkaleClassLoader.java +++ b/src/main/java/org/redkale/util/RedkaleClassLoader.java @@ -67,6 +67,7 @@ public class RedkaleClassLoader extends URLClassLoader { "org.redkale.net.http", "org.redkale.net.sncp", "org.redkale.persistence", + "org.redkale.props.spi", "org.redkale.schedule", "org.redkale.schedule.spi", "org.redkale.service", @@ -564,4 +565,30 @@ public class RedkaleClassLoader extends URLClassLoader { } } } + + public static class DynBytesClassLoader extends ClassLoader { + + private final Map classes = new HashMap<>(); + + public DynBytesClassLoader(ClassLoader parent) { + super(parent); + } + + @Override + public Class findClass(String name) throws ClassNotFoundException { + byte[] classData = classes.get(name); + if (classData == null) { + return super.findClass(name); + } + return super.defineClass(name, classData, 0, classData.length); + } + + public final Class loadClass(String name, byte[] b) { + return defineClass(name, b, 0, b.length); + } + + public final void addClass(String name, byte[] b) { + classes.put(name, b); + } + } }