二进制字节码文件的应用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_29956725/article/details/87865571
Java字节码生成开源框架有Javassist,ASM  Javassist已经加入了JBoss,JBoss用此实现了其动态AOP框架

ASM操作级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解,Spring 的cglib代理是用的是asm的这种方式

 

package cn.spring.test.utils;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import cn.spring.test.domain.Hello;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;

public class JavassistUtils {


    /**
     * Java字节码生成开源框架有Javassist,ASM  Javassist已经加入了JBoss,JBoss用此实现了其动态AOP框架
     * ASM操作级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解,Spring 的cglib代理是用的是asm的这种方式
     *
     * @param args
     * @throws NotFoundException
     * @throws CannotCompileException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws ClassNotFoundException
     * @throws IOException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     */
    public static void main(String[] args) throws NotFoundException,
            CannotCompileException, InstantiationException, IllegalAccessException, ClassNotFoundException, IOException, NoSuchMethodException, InvocationTargetException {

        arroundMethod();
        // assistMethod(); 只能修改一次
        generatorClass();
    }

    static void arroundMethod() throws NotFoundException,
            CannotCompileException, InstantiationException, IllegalAccessException, ClassNotFoundException {


        //~加上报错,和类加载有关系,这里new的话会把Hello类加载,之后再加载的话就会报错
        //Hello hell=new Hello();
        //hell.sayHello();
        //~

        CtClass ctClass = ClassPool.getDefault().getCtClass("cn.spring.test.domain.Hello");
        CtMethod ctMethod = ctClass.getDeclaredMethod("sayHello");
        ctMethod.insertBefore("System.out.println(\"我是此方法执行前.....\");");  //相当于前置通知
        ctMethod.insertAfter("System.out.println(\"我是此方法执行后.....\");");  //相当于后置通知
        Class ch = ctClass.toClass();   //必须要有这句,相当于修改字节码文件内容
        Hello h = (Hello) ch.newInstance();
        h.sayHello();

        Hello hel = new Hello();
        hel.sayHello();
    }

    static void assistMethod() throws NotFoundException,
            CannotCompileException, InstantiationException, IllegalAccessException, ClassNotFoundException {


        //~加上报错,和类加载有关系,这里new的话会把Hello类加载,之后再加载的话就会报错
        //Hello hell=new Hello();
        //hell.sayHello();
        //~

        CtClass ctClass = ClassPool.getDefault().getCtClass("cn.spring.test.domain.Hello");
        CtMethod ctMethod = ctClass.getDeclaredMethod("sayHello");
        ctMethod.setBody("System.out.println(\"hi\");");  //修改其内容
        Class ch = ctClass.toClass();   //必须要有这句,相当于修改字节码文件内容
        Hello h = (Hello) ch.newInstance();
        h.sayHello();

        Hello hel = new Hello();
        hel.sayHello();
    }

    static void generatorClass() throws CannotCompileException, IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        ClassPool pool = ClassPool.getDefault();
        //创建Programmer类       
        CtClass cc = pool.makeClass("com.samples.Programmer");
        //定义code方法  
        CtMethod method = CtNewMethod.make("public void code(){}", cc);
        //插入方法代码  
        method.insertBefore("System.out.println(\"I'm a Programmer,Just Coding.....\");");
        cc.addMethod(method);


        Class ch = cc.toClass();


        Method[] methodArr = OKhttpTest.class.getDeclaredMethods();
        Method m = Class.forName("com.samples.Programmer").getDeclaredMethod("code", null);
        m.invoke(ch.newInstance(), null);

        //保存生成的字节码  
        //   cc.writeFile("d://temp");

    }

}

猜你喜欢

转载自blog.csdn.net/qq_29956725/article/details/87865571