今天看到一个很有趣的ASM+Spring的应用写法.可以根据接口定义自动生成具体的Dao.主要还是ASM不熟悉.所以决定从基础看起来.比如我要定义个类:
public class Example { public void Hello(String str) { System.out.println("Hello world! " + str); } }
如果我要定义一个ASM动态生成则:
public static void main(final String args[]) throws Exception { /* * 如果我要生成一个如下的java代码: * * public void Hello(String str) * { * System.out.println("Hello world! " + str); * } */ // 定义ClassWriter 准备写类 ClassWriter cw = new ClassWriter(0); cw.visit(V1_6, ACC_PUBLIC, "Example", null, "java/lang/Object", null); // 创建默认构造函数 MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mw.visitVarInsn(ALOAD, 0); mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); mw.visitInsn(RETURN); mw.visitMaxs(1, 1); mw.visitEnd(); //创建Hello方法 ,形参是 String MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "Hello", "(Ljava/lang/String;)V", null, null); mv.visitCode(); Label l0 = new Label(); mv.visitLabel(l0); mv.visitLineNumber(12, l0); mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitTypeInsn(NEW, "java/lang/StringBuffer"); mv.visitInsn(DUP); mv.visitLdcInsn("Hello world! "); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuffer", "<init>", "(Ljava/lang/String;)V"); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "toString", "()Ljava/lang/String;"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); Label l1 = new Label(); mv.visitLabel(l1); mv.visitLineNumber(13, l1); mv.visitInsn(RETURN); Label l2 = new Label(); mv.visitLabel(l2); mv.visitLocalVariable("this", "Lcom/test/Example;", null, l0, l2, 0); mv.visitLocalVariable("str", "Ljava/lang/String;", null, l0, l2, 1); mv.visitMaxs(4, 2); mv.visitEnd(); /* * 写入文件 */ byte[] code = cw.toByteArray(); FileOutputStream fos = new FileOutputStream("Example.class"); fos.write(code); fos.close(); /* * 从文件加载类 */ HelloWord loader = new HelloWord(); Class exampleClass = loader.defineClass("Example", code, 0, code.length); /* * 反射生成类,并传入参数 */ Object obj = exampleClass.getConstructor(null).newInstance(null); exampleClass.getMethod("Hello", new Class[] {String.class}) .invoke(obj, new Object[] {"zjy"}); }
最后输出就
Hello world! zjy