java ASM、Cglib、aop

ASM

我们知道Java是静态语言,而pythonruby是动态语言Java程序一旦写好很难在运行时更改类的行为,而pythonruby可以;不过java可以通过MagicASM等一些开源库去动态生成字节码文件;

 

它是一个Java字节码修改框架,能直接生成二进制类代码或者动态修改类代码,生成stub类或者其他类似代理类。ASM要比BCEL和SERP小的多,其核心部分才33KB,速度也要比这些工具快的多,大概要比BCEL快7倍,比SERP快11倍。由于ASM设计的目的就是在运行时使用,因此它的体积尽可能小,速度尽可能快;可以用于动态生成stub类和其他代理类,截获类调用,添加一些横向功能。采用这种接口,你可以简单的实现面向方面的功能,比如添加安全、事务、日志、过滤、编码、解码等等的功能,而且是纯粹热插拔的模式。总之使用动态代理能够实现许多AOP方面的功能;

 

代码参考:

 

Java代码

  1. import java.io.FileOutputStream;   
  2. import java.io.PrintStream;   
  3.   
  4. import org.objectweb.asm.ClassWriter;   
  5. import org.objectweb.asm.MethodVisitor;   
  6. import org.objectweb.asm.Opcodes;   
  7. import org.objectweb.asm.Type;   
  8. import org.objectweb.asm.commons.GeneratorAdapter;   
  9. import org.objectweb.asm.commons.Method;   
  10.   
  11. public class Helloworld extends ClassLoader implements Opcodes {   
  12.   
  13.   public static void main(final String args[]) throws Exception {   
  14.   
  15.     // creates a ClassWriter for the Example public class,   
  16.     // which inherits from Object   
  17.   
  18.      ClassWriter cw = new ClassWriter(0);   
  19.      cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);   
  20.      MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null,   
  21.         null);   
  22.      mw.visitVarInsn(ALOAD, 0);   
  23.      mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");   
  24.      mw.visitInsn(RETURN);   
  25.      mw.visitMaxs(1, 1);   
  26.      mw.visitEnd();   
  27.      mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main",   
  28.         "([Ljava/lang/String;)V", null, null);   
  29.      mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out",   
  30.         "Ljava/io/PrintStream;");   
  31.      mw.visitLdcInsn("Hello world!");   
  32.      mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",   
  33.         "(Ljava/lang/String;)V");   
  34.      mw.visitInsn(RETURN);   
  35.      mw.visitMaxs(2, 2);   
  36.      mw.visitEnd();   
  37.     byte[] code = cw.toByteArray();   
  38.      FileOutputStream fos = new FileOutputStream("Example.class");   
  39.      fos.write(code);   
  40.      fos.close();   
  41.      Helloworld loader = new Helloworld();   
  42.      Class exampleClass = loader   
  43.          .defineClass("Example", code, 0, code.length);   
  44.      exampleClass.getMethods()[0].invoke(null, new Object[] { null });   
  45.   
  46.     // ------------------------------------------------------------------------   
  47.     // Same example with a GeneratorAdapter (more convenient but slower)   
  48.     // ------------------------------------------------------------------------   
  49.   
  50.      cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);   
  51.      cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);   
  52.      Method m = Method.getMethod("void <init> ()");   
  53.      GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null,   
  54.          cw);   
  55.      mg.loadThis();   
  56.      mg.invokeConstructor(Type.getType(Object.class), m);   
  57.      mg.returnValue();   
  58.      mg.endMethod();   
  59.      m = Method.getMethod("void main (String[])");   
  60.      mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);   
  61.      mg.getStatic(Type.getType(System.class), "out", Type   
  62.          .getType(PrintStream.class));   
  63.      mg.push("Hello world!");   
  64.      mg.invokeVirtual(Type.getType(PrintStream.class), Method   
  65.          .getMethod("void println (String)"));   
  66.      mg.returnValue();   
  67.      mg.endMethod();   
  68.      cw.visitEnd();   
  69.      code = cw.toByteArray();   
  70.      loader = new Helloworld();   
  71.      exampleClass = loader.defineClass("Example", code, 0, code.length);   
  72.      exampleClass.getMethods()[0].invoke(null, new Object[] { null });   
  73.    }   
  74. }  

import java.io.FileOutputStream;

import java.io.PrintStream;

 

import org.objectweb.asm.ClassWriter;

import org.objectweb.asm.MethodVisitor;

import org.objectweb.asm.Opcodes;

import org.objectweb.asm.Type;

import org.objectweb.asm.commons.GeneratorAdapter;

import org.objectweb.asm.commons.Method;

 

public class Helloworld extends ClassLoader implements Opcodes {

 

  public static void main(final String args[]) throws Exception {

 

    // creates a ClassWriter for the Example public class,

    // which inherits from Object

 

    ClassWriter cw = new ClassWriter(0);

    cw.visit(V1_1, 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();

    mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main",

        "([Ljava/lang/String;)V", null, null);

    mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out",

        "Ljava/io/PrintStream;");

    mw.visitLdcInsn("Hello world!");

    mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",

        "(Ljava/lang/String;)V");

    mw.visitInsn(RETURN);

    mw.visitMaxs(2, 2);

    mw.visitEnd();

    byte[] code = cw.toByteArray();

    FileOutputStream fos = new FileOutputStream("Example.class");

    fos.write(code);

    fos.close();

    Helloworld loader = new Helloworld();

    Class exampleClass = loader

        .defineClass("Example", code, 0, code.length);

    exampleClass.getMethods()[0].invoke(null, new Object[] { null });

 

    // ------------------------------------------------------------------------

    // Same example with a GeneratorAdapter (more convenient but slower)

    // ------------------------------------------------------------------------

 

    cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);

    cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);

    Method m = Method.getMethod("void <init> ()");

    GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null,

        cw);

    mg.loadThis();

    mg.invokeConstructor(Type.getType(Object.class), m);

    mg.returnValue();

    mg.endMethod();

    m = Method.getMethod("void main (String[])");

    mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);

    mg.getStatic(Type.getType(System.class), "out", Type

        .getType(PrintStream.class));

    mg.push("Hello world!");

    mg.invokeVirtual(Type.getType(PrintStream.class), Method

        .getMethod("void println (String)"));

    mg.returnValue();

    mg.endMethod();

    cw.visitEnd();

    code = cw.toByteArray();

    loader = new Helloworld();

    exampleClass = loader.defineClass("Example", code, 0, code.length);

    exampleClass.getMethods()[0].invoke(null, new Object[] { null });

  }

}

上面的例子分别使用ASMMethodVisitorGeneratorAdapter两种方式来动态生成Example并调用打印语句。

你可能感兴趣的:(cglib)