首页 > 其他 > 详细

字节码增强-learnning

时间:2020-08-20 16:19:54      阅读:52      评论:0      收藏:0      [点我收藏+]

 

jvm加载java的过程主要是:

编写java文件-》进行java文件的编译-》生成.class字节码文件-》jvm通过类加载器去加载生成的二进制文件

java编译器将源码文件编译称为二进制的.class文件

 

为什么要进行字节码增强操作?

不想修改源码,但是又想加入新功能,让程序按照我们的预期去运行,可以通过编译过程和加载过程中去做

相应的操作,

简单来讲就是:将生成的.class文件修改或者替换称为我们需要的目标.class文件。

 

需要依赖第三方的工具去实现字节码增强

这里使用javassist实现;

 

 

步骤:

/**
 * 步骤1:编写你最初的业务类,实现业务功能
 */
public class BaseService {
    public void basePrint(Map map){
        System.out.println(map.toString());
    }
}

 

/**
 * 步骤2:编写你需要的对业务类进行增强的类或者内容
 */
public class ExBaseService {
    public static  void exPrint(Map map){
        System.out.println("exbaseService增强的功能==需要增强的方法之前");
    }

    public static  void  exPrintL(Map map){
        System.out.println("exbaseService增强的功能==需要增强的方法之后");
    }
}

 

/**
 * 步骤3:编写增强的工具类,之后直接调用后再使用原来的业务类方法就实现增强了
 * ClassPool其实是一张保存了CtClass信息的哈希表,key=类的全限定类名,value=类名对应的CtClass对象。
 *          当需要对某个类修改的时候,通过方法getCtClass(className)从classpool获取到相应的CtClass
 * CtClass:编译时的类信息,一个class文件在代码中的抽象表现形式,全限定类名可以获取CtClass对象,用于表示这个类文件
 * CtMethod: 类中的方法 定义或修改
 * CtField:  类中的属性 定义或修改
 *
 * javassist 增强代码片段是字符串编写,以$开头用于表示方法或构造函数参数或方法返回值
 */
public class ServiceUtils {
    public static void done() throws NotFoundException, CannotCompileException {
        ClassPool classPool = ClassPool.getDefault();//获取默认的类池
        //通过全限定类名从类池获取对应需要增强的类
        CtClass base = classPool.getOrNull("com.quan.security.intecepter.BaseService");
        if (base  == null){
            System.out.println("can not found");
            return;
        }
        //通过方法getDeclaredMethod和类中需要增强的方法名字得到CtMethod类型的方法抽象
        CtMethod basemethod = base.getDeclaredMethod("basePrint");
        //组合增强字符串,使用$1获取方法的参数。
        StringBuffer sbf = new StringBuffer();
        sbf.append("{");
        sbf.append("com.quan.security.intecepter.ExBaseService.exPrint($1);");
        sbf.append("}");

        //进行增强,调用之前增强
        basemethod.insertBefore(sbf.toString());

        StringBuffer sbf2 = new StringBuffer();
        sbf2.append("{");
        sbf2.append("com.quan.security.intecepter.ExBaseService.exPrintL($1);");
        sbf2.append("}");

        //进行增强,调用需要增强方法之后增强
        basemethod.insertAfter(sbf2.toString());
        //替换增强后的字节码
        base.toClass();
    }
}

 

public class IntecepterTest {
    /**
     * 调用增强工具类,使最初的业务类进行增强,
     * 随后调用业务类,查看是否增强
     * @param args
     */
    public static void main(String[] args)  {
        try {
            ServiceUtils.done();
        } catch (NotFoundException e) {
            e.printStackTrace();
        } catch (CannotCompileException e) {
            e.printStackTrace();
        }
        BaseService baseService = new BaseService();
        Map<String,String> map1 = new HashMap<>();
        map1.put("name","quan");
        baseService.basePrint(map1);
    }
}

 

结果:

exbaseService增强的功能==需要增强的方法之前
{name=quan}
exbaseService增强的功能==需要增强的方法之后

 

字节码增强-learnning

原文:https://www.cnblogs.com/java-quan/p/13534603.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!