0

0

Java中的Javassist怎么使用

王林

王林

发布时间:2023-05-17 20:07:10

|

1479人浏览过

|

来源于亿速云

转载

    开篇

    说起 aop 小伙伴们肯定很熟悉,无论是 jdk 动态代理或者是 cglib 等,其底层都是通过操作 java 字节码来实现代理。asm、aspectj和javassist等是常用的操作字节码的技术。

    ASM 其设计和实现是尽可能小而且快,更专注于性能。它在指令的层面来操作,所以使用它需要对 JVM 的指令有所了解,门槛较高,CGLIB 就使用了 ASM 技术。

    AspectJ 扩展了 Java 语言,定义了一系列 AOP 语法,在 JVM 中运行需要使用特定的编译器生成遵守 Java 字节码规范的 Class 文件,Spring AOP 使用了 AspectJ 。

    Javassist 直接使用 Java 编码的形式操作字节码,简单易上手,性能高于反射,相比于 ASM 稍低。

    Javassist 常用类

    Javassist 抽象出一个 ClassPool 对象来操作 Java 类,可以通过 ClassPool.getDefault() 来获取默认的 ClassPool 。常用的对象:

    立即学习Java免费学习笔记(深入)”;

    CtClass:代表一个 Class 的实例,可以通过类的全限定名来获取 CtClass 对象,其中包含了对 Class 的各种操作。

    ClassPool:通过 HashTable 保存了路径下的 CtClass 信息,key为类的全限定名称,value 为类名对应的 CtClass 对象。

    CtMethod、CtField:抽象出类的方法和属性,可以用于定义或修改方法和字段。

    jspgou网店系统
    jspgou网店系统

    JSPGOU一直以来都和jeecms、jeebbs一样,是收费软件,但是从2014年7月12日开始,开始jspgou发布第一个免费版,金磊科技承诺:永远不向使用jspgou免费版用户索取任何费用,为免费用户提供更好的技术支持服务,根据用户提出的完善建议快速完善jspgou系统。 jspgou系统使命:做中国最优秀的免费网店系统,让更多的用户了解和使用java产品。 jspgou免费版适用对象:不限

    下载

    Javassist 的使用

    依赖

    
      org.javassist
      javassist
      3.27.0-GA
    

    代码示例

    // 获取默认类池
      ClassPool classPool = ClassPool.getDefault();
      // 1. 创建空类
      CtClass ctClass = classPool.makeClass("com.aysaml.demo.javassist.User");
    
      // 2. 创建 String 类型的 name 字段
      CtField field = new CtField(classPool.get("java.lang.String"), "name", ctClass);
      // 设置字段访问级别 private
      field.setModifiers(Modifier.PRIVATE);
      // 增加字段
      ctClass.addField(field);
    
      // 3. 增加 getter & setter 方法
      ctClass.addMethod(CtNewMethod.getter("getName", field));
      ctClass.addMethod(CtNewMethod.setter("setName", field));
    
      // 4. 增加无参构造方法:其中 $0 表示 this,$1 表示参数
      CtConstructor noArgsCons = new CtConstructor(new CtClass[] {}, ctClass);
      noArgsCons.setBody("{$0.name=\"mark\";}");
      ctClass.addConstructor(noArgsCons);
    
      // 5. 增加有参构造方法
      CtConstructor hasArgsCons =
        new CtConstructor(new CtClass[] {classPool.get("java.lang.String")}, ctClass);
      hasArgsCons.setBody("{$0.name=$1;}");
      ctClass.addConstructor(hasArgsCons);
    
      // 6. 创建方法
      CtMethod method = new CtMethod(CtClass.voidType, "printName", new CtClass[] {}, ctClass);
      method.setBody("{System.out.println($0.name);}");
      ctClass.addMethod(method);
    
      // 7. 生成类文件:可指定路径,默认为当前项目根目录
      ctClass.writeFile();
    
      // 8. 创建类实例
      Object person = ctClass.toClass().newInstance();

    如何实现类似 AOP 的功能

    javassist 对于编程化的操作字节码是很简单易懂的,我们以在方法的开头结尾打印信息为例:

    public class Cat {
    
     /** 记录喵喵喵的次数 */
     private int num;
    
     public void miao() {
      this.num++;
     }
    }

    我们要在 miao( ) 方法的前增加声音输出:

    public static void main(String[] args) throws NotFoundException, CannotCompileException {
      ClassPool classPool = ClassPool.getDefault();
      // 获取 Cat 类的 CtClass 对象
      CtClass catClass = classPool.get("com.aysaml.demo.javassist.Cat");
      // 获取 miao( ) 方法
      CtMethod method = catClass.getDeclaredMethod("miao");
      method.insertBefore("System.out.println(\"miao~\");");
      // 加载修改过的类,注意必须要保证调用前这个类没有被加载过
      catClass.toClass();
      //测试
      Cat cat = new Cat();
      cat.miao();
     }

    注意到,在使用 catClass.toClass() 加载被修改过的类时,强调必须保证在调用前这个类没有被加载过,否则会报 attempted duplicate class definition for name 异常。

    我们知道一个类是不能被一个类加载器加载两次的,所以为了解决这个问题,需要制定一个没有加载过该类的 Classloader,Javassist 提供了一个 ClassLoader ,如下:

    public class Cat {
    
     /** 记录喵喵喵的次数 */
     private int num;
    
     public void miao() {
      System.out.println("调用了 miao 方法");
      this.num++;
     }
    
     public static void main(String[] args) throws Exception{
      ClassPool classPool = ClassPool.getDefault();
      // 获取 Cat 类的 CtClass 对象
      CtClass catClass = classPool.get("com.aysaml.demo.javassist.Cat");
      // 获取 miao( ) 方法
      CtMethod method = catClass.getDeclaredMethod("miao");
      method.insertBefore("System.out.println(\"miao~\");");
      // 重新设置一个 Classloader
      Loader classLoader = new Loader(classPool);
      Class clazz = classLoader.loadClass("com.aysaml.demo.javassist.Cat");
      // 调用修改过的类的方法
      clazz.getDeclaredMethod("miao").invoke(clazz.newInstance());
     }
    }

    执行结果为:

    Java中的Javassist怎么使用

    相关文章

    java速学教程(入门到精通)
    java速学教程(入门到精通)

    java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

    下载

    相关标签:

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

    热门AI工具

    更多
    DeepSeek
    DeepSeek

    幻方量化公司旗下的开源大模型平台

    豆包大模型
    豆包大模型

    字节跳动自主研发的一系列大型语言模型

    通义千问
    通义千问

    阿里巴巴推出的全能AI助手

    腾讯元宝
    腾讯元宝

    腾讯混元平台推出的AI助手

    文心一言
    文心一言

    文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

    讯飞写作
    讯飞写作

    基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

    即梦AI
    即梦AI

    一站式AI创作平台,免费AI图片和视频生成。

    ChatGPT
    ChatGPT

    最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

    相关专题

    更多
    spring框架介绍
    spring框架介绍

    本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

    116

    2025.08.06

    Java Spring Security 与认证授权
    Java Spring Security 与认证授权

    本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

    40

    2026.01.26

    class在c语言中的意思
    class在c语言中的意思

    在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

    469

    2024.01.03

    python中class的含义
    python中class的含义

    本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

    17

    2025.12.06

    2026赚钱平台入口大全
    2026赚钱平台入口大全

    2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

    12

    2026.01.31

    高干文在线阅读网站大全
    高干文在线阅读网站大全

    汇集热门1v1高干文免费阅读资源,涵盖都市言情、京味大院、军旅高干等经典题材,情节紧凑、人物鲜明。阅读专题下面的文章了解更多详细内容。

    6

    2026.01.31

    无需付费的漫画app大全
    无需付费的漫画app大全

    想找真正免费又无套路的漫画App?本合集精选多款永久免费、资源丰富、无广告干扰的优质漫画应用,涵盖国漫、日漫、韩漫及经典老番,满足各类阅读需求。阅读专题下面的文章了解更多详细内容。

    10

    2026.01.31

    漫画免费在线观看地址大全
    漫画免费在线观看地址大全

    想找免费又资源丰富的漫画网站?本合集精选2025-2026年热门平台,涵盖国漫、日漫、韩漫等多类型作品,支持高清流畅阅读与离线缓存。阅读专题下面的文章了解更多详细内容。

    1

    2026.01.31

    漫画防走失登陆入口大全
    漫画防走失登陆入口大全

    2026最新漫画防走失登录入口合集,汇总多个稳定可用网址,助你畅享高清无广告漫画阅读体验。阅读专题下面的文章了解更多详细内容。

    7

    2026.01.31

    热门下载

    更多
    网站特效
    /
    网站源码
    /
    网站素材
    /
    前端模板

    精品课程

    更多
    相关推荐
    /
    热门推荐
    /
    最新课程
    Kotlin 教程
    Kotlin 教程

    共23课时 | 3万人学习

    C# 教程
    C# 教程

    共94课时 | 8.1万人学习

    Java 教程
    Java 教程

    共578课时 | 54万人学习

    关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
    php中文网:公益在线php培训,帮助PHP学习者快速成长!
    关注服务号 技术交流群
    PHP中文网订阅号
    每天精选资源文章推送

    Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号