首页 > 编程语言 >Java中使用javassist库动态操作类

Java中使用javassist库动态操作类

时间:2022-11-21 00:33:38浏览次数:58  
标签:Java ccs class ctClass emp id 动态 public javassist

它是一个用来处理 Java 字节码的类库,也就是说没有.java文件,用它可以直接造一个.class文件。

直接创建一个class类

例如:

import javassist.*;
/**
 * 使用javassist库
 */
public class TestClass {
    public static void main(String[] args) throws Exception {

        //1.获取一个ctclass池
        ClassPool pool = ClassPool.getDefault();
        //2.从池中,创建一个指定名字的class对象
        CtClass ccs = pool.makeClass("lrj.annotation.emp");

        //创建属性并且添加到emp.class中
        CtField cf1 = CtField.make("private int id;",ccs);
        CtField cf2 = CtField.make("private String name;",ccs);
        ccs.addField(cf1);
        ccs.addField(cf2);

        //创建方法并且添加到emp.class中
        CtMethod cm1 = CtMethod.make("public int getId(){return id;}",ccs);
        CtMethod cm2 = CtMethod.make("public void setId(int id){this.id=id;}",ccs);
        ccs.addMethod(cm1);
        ccs.addMethod(cm2);

        //创建构造器并且添加到emp.class中
        CtConstructor cc1 = new CtConstructor(//声明构造器的两个参数
                new CtClass[]{CtClass.intType,pool.get("java.lang.String")},ccs);
        cc1.setBody("{this.id = $1;this.name=$2;}");//方法体,$1表示第一个参数,$2表示第二个参数
        ccs.addConstructor(cc1);

        //将以上构建好的类写到目的文件夹下
        String destFolder = "d:/my_file";
        ccs.writeFile(destFolder);
        System.out.println("class生成成功!");
    }
}

运行结果:

 

使用反编译器反编译结果:(反编译器:https://www.cr173.com/soft/35032.html    )

 

 

通过反射访问类的数据

准备好一个emp类:

package lrj.annotation;

public class emp {
    private int id;
    private String name;

    public emp() { }

    public emp(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
查看类 内容

javassist和java内置的Class类非常相似。

通过地址获取类信息

public class TestClass {
    public static void main(String[] args) throws Exception {
        //1.获取ctClass池
        ClassPool pool = ClassPool.getDefault();
        //2.获取一个class对象
        CtClass ccs = pool.get("lrj.annotation.emp");
        System.out.println("获取完成类名:"+ccs.getName());
        System.out.println("获取包名:"+ccs.getPackageName());
        System.out.println("获取类名:"+ccs.getSimpleName());
        //把class放进一个字节数组中。
        byte[] datas = ccs.toBytecode();
        System.out.println(datas.length);
    }
}

运行结果:

 

 

 

给类添加方法

public class TestClass {
    public static void main(String[] args) throws Exception {
        //1.获取ctClass池
        ClassPool pool = ClassPool.getDefault();
        //2.获取一个class对象
        CtClass ctClass = pool.get("lrj.annotation.emp");

        //声明一个add方法
        CtMethod ctMethod1 = new CtMethod(CtClass.intType,//返回值
                "add",//函数名
                new CtClass[]{CtClass.intType,CtClass.intType},//参数类型
                ctClass);
        ctMethod1.setModifiers(Modifier.PUBLIC);//设置修饰符
        //编写方法体,$1表示第一个参数,$2表示第二个参数
        ctMethod1.setBody("{return $1+$2;}");
        //方法加入类中
        ctClass.addMethod(ctMethod1);

        //CtClass转为Class对象
        Class aClass=ctClass.toClass();
        emp e1 = (emp) aClass.getConstructor().newInstance();
        //获取刚刚创建的方法,并调用。
        Method m1 = aClass.getDeclaredMethod("add",int.class,int.class);
        int temp = (int) m1.invoke(e1,12,24);
        System.out.println(temp);
    }
}

运行结果:

 

 

 

改变一个方法的内部结构

public class TestClass {
    public static void main(String[] args) throws Exception {
        //1.获取ctClass池
        ClassPool pool = ClassPool.getDefault();
        //2.获取一个class对象
        CtClass ctClass = pool.get("lrj.annotation.emp");

        CtMethod ctMethod1 = ctClass.getDeclaredMethod("getName");
        //在方法体的最上方添加代码
        ctMethod1.insertBefore("System.out.println(\"------start------\");");
        //在指定的行加入代码。
        //ctMethod1.insertAt(14,"");
        //在方法体的最下方,return语句之前,添加代码
        ctMethod1.insertAfter("System.out.println(\"-------end------\");");

        //CtClass转为Class对象
        Class aClass=ctClass.toClass();
        emp e1 = (emp) aClass.getConstructor().newInstance();
        //获取刚刚创建的方法,并调用。
        Method m1 = aClass.getDeclaredMethod("getName");
        m1.invoke(e1);
    }
}

运行结果:

 

 新建属性、创建set、get方法:

public class TestClass {
    public static void main(String[] args) throws Exception {
        //1.获取ctClass池
        ClassPool pool = ClassPool.getDefault();
        //2.获取一个class对象
        CtClass ctClass = pool.get("lrj.annotation.emp");

        //给ctClass新建一个属性
        CtField ctField1 = new CtField(CtClass.intType,"number",ctClass);
        ctField1.setModifiers(Modifier.PUBLIC);//设置访问权限
        ctClass.addField(ctField1);

        //获取指定属性
        //ctClass.getDeclaredField(name)

        //给属性加set、get方法
        ctClass.addMethod(CtNewMethod.setter("setNumber",ctField1));
        ctClass.addMethod(CtNewMethod.getter("getNumber",ctField1));
    }
}

总结:

使用javassist库,我们可以更加便捷地操作字节码文件。

与Class相辅相成。

 

标签:Java,ccs,class,ctClass,emp,id,动态,public,javassist
From: https://www.cnblogs.com/lurenjia-bky/p/16910136.html

相关文章

  • 新手随笔java+cpp
    随便写写关于java和cpp感悟·1.初学java(在学ing),学了几个月cpp(也不算熟练,但是目前比java好点)·2.java应该是更灵活的,比如【一些灵活点和区别】,二维数组不是非要矩阵形......
  • javascript - 练习题:事件练习 - 贪吃蛇
    贪吃蛇原生JS(非面向对象的方式),渡一教学的笔记;地图坐标{0,0}{1,0}{2,0}{3,0}{4,0}{0,1}{1,1}{2,1}{3,1}{4,1}{0,2}{1,2}{2,2}{3,2}{4,2}{0,3}{1,3}{2,3}{3,3}{4,3}{0,4}{1,4}......
  • java-网络编程
    一、概述1、两个主要问题(1)如何准确定位网络上一台或多台主机;定位主机上的特定应用(2)找到主机后如何可靠高效的进行数据传输2、两个要素(1)IP和端口号(2)网络通信协议(OSI参......
  • Wust Java Club 2022-2023上半学年中期考核
    WustJavaClub2022-2023上半学年中期考核前言提交时的注意事项不可写入包名,如packageedu.wust必须有且只能有一个公有类publicclassMain,若有其他类,不应给其赋为......
  • JAVA 代码优化
    1基本类型使用优化1.1尽量重用对象特别是对于String对象的使用,如需拼接字符串,使用如下例子://拼接字符串,不重视效率的写法Stringstr1="aaa";str1=str1+"bbb"......
  • Java_JDBC
    JDBC一、JDBC简介1、概念:​ JDBC就是使用Java语言操作关系型数据库的一套API​ 全称:(JavaDataBaseConnectivity)Java数据库连接2、本质:为了使得Java代码可以......
  • 前端权限动态路由
    前端权限控制思路菜单的控制登陆请求时,会得到权限数据,需要后端返回数据,前端根据权限数据,展示对应的菜单,点击菜单才能看到相应的界面界面的控制如果用户没有......
  • 力扣33(java&python)-搜索旋转排序数组(中等)
    题目:整数数组nums按升序排列,数组中的值互不相同。在传递给函数之前,nums在预先未知的某个下标k(0<=k<nums.length)上进行了旋转,使数组变为[nums[k],nums[k+1],......
  • Java学习一
    一.小结1.计算机是储存和处理数据的电子设备2.计算机包括硬件和软件两个部分3.硬件是计算机中可以看见的物理部分4.计算机程序,也就是通常所说的软件,是一些看不见的指令......
  • java集合类 collection接口,List集合
    java集合类:collection接口,List集合 在java.util包中提供了一些集合类,集合类又被称为容器,常用的有List集合,Set集合,Map集合。下面将介绍collection接口和List集合。1.co......