尚学堂 217 java中的字节码操作2

 

复制代码
package com.bjsxt.test;


@Author(name="gaoqi", year=2014) 
public class Emp {
    
    private int empno;
    private String ename;
    
    public void sayHello(int a){
        System.out.println("sayHello,"+a);
    }
    
    public int getEmpno() {
        return empno;
    }
    public void setEmpno(int empno) {
        this.empno = empno;
    }
    public String getEname() {
        return ename;
    }
    public void setEname(String ename) {
        this.ename = ename;
    }
    
    public Emp(int empno, String ename) {
        super();
        this.empno = empno;
        this.ename = ename;
    }
    
    public Emp() {
    }
}
复制代码

 

 

我们测试javaAssit的常用api代码

复制代码
package com.bjsxt.test;

import java.lang.reflect.Method;
import java.util.Arrays;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.Modifier;
import javassist.NotFoundException;

/**
 * 测试javassist的API
 * @author 尚学堂高淇 www.sxt.cn
 *
 */
public class Demo02 {
    /**
     * 处理类的基本用法
     * @throws Exception 
     */
    public static void test01() throws Exception{
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.get("com.bjsxt.test.Emp");
        
        byte[] bytes = cc.toBytecode();
        System.out.println(Arrays.toString(bytes));
        
        System.out.println(cc.getName()); //获取类名
        System.out.println(cc.getSimpleName()); //获取简要类名
        System.out.println(cc.getSuperclass()); //获得父类
        System.out.println(cc.getInterfaces()); //获得接口
        
    }
    
    /**
     * 测试产生新的方法
     * @throws Exception 
     */
    public static void test02() throws Exception{
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.get("com.bjsxt.test.Emp");
        
//        CtMethod m = CtNewMethod.make("public int add(int a,int b){return a+b;}", cc);
        
        /*
        *CtClass.intType,CtClass.intType是add函数的两个形参的类型这里没有制定形参的名字,这里通过占位符来指定形参名字
        $0表示this对象
        $1表示第一个形参
        $2表示第二个形参
        */
        CtMethod m = new CtMethod(CtClass.intType,"add",
                new CtClass[]{CtClass.intType,CtClass.intType},cc);
        m.setModifiers(Modifier.PUBLIC);
        m.setBody("{System.out.println(\"www.sxt.cn\");return $1+$2;}");
        
        cc.addMethod(m);
        
        //通过反射调用新生成的方法
        Class clazz = cc.toClass();
        Object obj = clazz.newInstance();  //通过调用Emp无参构造器,创建新的Emp对象
        Method method = clazz.getDeclaredMethod("add", int.class,int.class);
        Object result = method.invoke(obj, 200,300);
        System.out.println(result);
    }
    
    /**
     * 修改已有的方法的信息,修改方法体的内容
     * @throws Exception
     */
    public static void test03() throws Exception{
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.get("com.bjsxt.test.Emp");
        
        CtMethod cm = cc.getDeclaredMethod("sayHello",new CtClass[]{CtClass.intType});
        cm.insertBefore("System.out.println($1);System.out.println(\"start!!!\");");
        /*
        *在每一行前面加入内容
        */
        cm.insertAt(9, "int b=3;System.out.println(\"b=\"+b);");
        cm.insertAfter("System.out.println(\"end!!!\");");
        
        //通过反射调用新生成的方法
        Class clazz = cc.toClass();
        Object obj = clazz.newInstance();  //通过调用Emp无参构造器,创建新的Emp对象
        Method method = clazz.getDeclaredMethod("sayHello", int.class);
        method.invoke(obj, 300);
    }

    /**
     * 添加新的属性的操作
     * @throws Exception
     */
    public static void test04() throws Exception{
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.get("com.bjsxt.test.Emp");
        
//        CtField f1 = CtField.make("private int empno;", cc);
        CtField f1 = new CtField(CtClass.intType,"salary",cc);
        f1.setModifiers(Modifier.PRIVATE);
        cc.addField(f1);
        
//        cc.getDeclaredField("ename");   //获取指定的属性
        
        //增加相应的set和get方法
        cc.addMethod(CtNewMethod.getter("getSalary", f1));;
        cc.addMethod(CtNewMethod.getter("setSalary", f1));;
        
    }
    
    /**
     * 构造方法的操作
     * @throws Exception
     */
    public static void test05() throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.get("com.bjsxt.test.Emp");
        
        CtConstructor[] cs = cc.getConstructors();
        for (CtConstructor c : cs) {
            System.out.println(c.getLongName());
        }
    }
    
    
    public static void test06() throws Exception{
         CtClass cc = ClassPool.getDefault().get("com.bjsxt.test.Emp"); 
         Object[] all = cc.getAnnotations();
         Author a = (Author)all[0]; 
         String name = a.name();
         int year = a.year();
         System.out.println("name: " + name + ", year: " + year);

    }
    
    
    public static void main(String[] args) throws Exception {
        test06();
    }
}
复制代码

 

package com.bjsxt.test;
public @interface Author { 
          String name(); 
           int year();
 }

 

posted on   luzhouxiaoshuai  阅读(145)  评论(0编辑  收藏  举报

编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示