Java300StudyNote(5)-Javassist常用API

本文介绍JavaAssist的基本使用,涵盖类操作、方法增删改、属性及构造函数操作等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、Javassist操作类的常用方法

测试代码:

@Test
    public void test01() throws Exception {
        // 获取类池
        ClassPool pool = ClassPool.getDefault();
        // 获取user类对象
        // com.maple.testJavassist.User只是一个普通的测试类
        CtClass userClass = pool.get("com.maple.testJavassist.User");
        // 转化为字节码
        byte[] bytecode = userClass.toBytecode();
        System.out.println("User.class字节码为:" + Arrays.toString(bytecode));
        // 获取全类名
        System.out.println("User类全类名为:" + userClass.getName());
        // 获取类名
        System.out.println("User类名为:" + userClass.getSimpleName());
        // 获取接口
        System.out.println("User类名为:" + userClass.getInterfaces());
        //获取父类
        System.out.println("User类名为:" + userClass.getSuperclass());
    }

测试结果:

这里写图片描述

2、javassist新建Method方法

测试代码:

@Test
    public void test02() throws Exception {
        /*************************************
         *          创建新增方法
         * ***********************************/
        // 获取类池
        ClassPool pool = ClassPool.getDefault();
        // 获取user类对象
        // com.maple.testJavassist.User只是一个普通的测试类
        CtClass userClass = pool.get("com.maple.testJavassist.User");
        // 在User类中新增一个方法
        /**
         * 新增一个add(int a,int b)方法 
         * public int add (int a ,int b){
         *      return a+b;
         * }
         */
        CtMethod newMethod = new CtMethod(
                    CtClass.intType, //方法返回值类型
                    "add", //方法名
                    //方法参数类型
                    new CtClass[] { CtClass.intType, CtClass.intType },
                    userClass//这个新方法将要添加到user类上
                );
        newMethod.setModifiers(Modifier.PUBLIC);//设置方法修饰符
        newMethod.setBody("{return $1+$2;}");//添加方法体
        //将新方法加到user类中注意这里操作的只是字节码
        userClass.addMethod(newMethod);

        /*************************************
         *          反射新增方法
         * ***********************************/

        //通过反射调用新添加的类
        Class<?>clazz = userClass.toClass();
        //获取一个user实例对象
        User userNewInstance = (User)clazz.newInstance();
        //获取新增方法
        Method m = clazz.getDeclaredMethod("add", int.class,int.class);
        Object result = m.invoke(userNewInstance, 100,200);
        System.out.println("执行add方法结果为"+result);
    }

测试结果:
这里写图片描述

注意:这里对其中的newMethod.setBody("{return $1+$2;}");做出解释
为什么要采用$1,和$2呢?
首先先说明$1和$2代表的是add(int a ,int b)的两个形参,是为了操作字节码的时候代表形参的。以下是常用的一些操作方法时的占位符

以下表格的例子都以add(int a,int b)为原型

占位符解释
$0表示方法中的隐式参数this
$1,$2…分别依次代表方法中的参数 例 int a,和 int b
\args表示所有形式参数的数组对象,args[0]代表 $1,args[1]代表$2依次类推
$$所有方法参数的简写 例 add($$)=add(\$1,\$2)
$cflow方法调用的深度,可以理解为递归调用时处在被调用的第几步
$r方法返回值的类型
$_方法返回值
addCatch()方法中加入try catch 块,$e代表异常对象
$classthis的类型(Class) 也就是$0的类型
$sig方法参数的类型数组

3、Javassist修改类中已有的方法

测试代码

@Test
    public void test03() throws Exception {
        // 获取类池
        ClassPool pool = ClassPool.getDefault();
        // 获取user类对象
        // com.maple.testJavassist.User只是一个普通的测试类
        CtClass userClass = pool.get("com.maple.testJavassist.User");
        //获取hello方法对象
        CtMethod hello = userClass.getDeclaredMethod("hello", null);
        hello.insertBefore("System.out.println(\"insertBefore==>在hello方法体的前面插入\");");
        hello.insertAfter("System.out.println(\"insertAfter==>在hello方法体的最后插入\");");
        hello.insertAt(6, "System.out.println(\"insertAt==>在第6行插入\");");

        /*************************************
         *          反射测试方法
         * ***********************************/

        //通过反射调用新添加的类
        Class<?>clazz = userClass.toClass();
        //获取一个user实例对象
        User userNewInstance = (User)clazz.newInstance();
        //获取新增方法
        Method m = clazz.getDeclaredMethod("hello");
        m.invoke(userNewInstance);
    }

测试结果

这里写图片描述

4、Javassit新建属性以及setter和getter方法

测试代码

@Test
    public void test04() throws Exception {
        // 获取类池
        ClassPool pool = ClassPool.getDefault();
        // 获取user类对象
        // com.maple.testJavassist.User只是一个普通的测试类
        CtClass userClass = pool.get("com.maple.testJavassist.User");
        //创建一个属性 private String name;
        CtField f1 = new CtField(
                    pool.get("java.lang.String"),//属性数据类型 
                    "name", //属性名
                    userClass
                );//属性将要加在哪个类上
        //添加属性
        userClass.addField(f1);

        //快速创建该新增属性f1的setter和getter方法
        userClass.addMethod(CtNewMethod.setter("setName", f1));
        userClass.addMethod(CtNewMethod.getter("getName", f1));

    }

5、Javassist构造函数操作

具体测试和之前反射测试相同这里只列出相关API的使用和注解

测试代码:

    @Test
    public void test05() throws Exception {
        // 获取类池
        ClassPool pool = ClassPool.getDefault();
        // 获取user类对象
        // com.maple.testJavassist.User只是一个普通的测试类
        CtClass userClass = pool.get("com.maple.testJavassist.User");
        //获取所有的构造方法
        CtConstructor[] constructors = userClass.getConstructors();
        for (CtConstructor c : constructors) {
            c.insertBefore("insertBefore");
            c.insertAfter("insertBefore");
            c.insertAt(8, "insertAt");
        }
    }

6、Javassist注解操作

测试代码

自定义注解Level.java

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Level {
    String value();
}

User.java
User类有以下的注解

@Level("会员")
public class User {

    public void hello() {
        System.out.println("hello方法你好");
    }

}

测试程序

@Test
    public void test06() throws Exception {
        // 获取类池
        ClassPool pool = ClassPool.getDefault();
        // 获取user类对象
        // com.maple.testJavassist.User只是一个普通的测试类
        CtClass userClass = pool.get("com.maple.testJavassist.User");
        Level level = (com.maple.testJavassist.Level) userClass.getAnnotation(Level.class);
        System.out.println(level.value());
    }

测试结果
这里写图片描述

小结:

本篇文件分别介绍了javassit的一些常用API,包括对类的操作,如何新增方法,如何对已有方法进行修改,如何新增属性,如何快速创建setter和getter方法,操作构造器,注解的操作,这些都是javassist的常用API,要想了解更多更细的API可以参见javassist的官网查看官方文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值