Eclipse下Javassist正确使用方法

Eclipse下Javassist正确使用方法

        这两天看到Hibernate的代理部分,第一反应是底层使用了反射,针对用户实体生成了代理类,后来反应过来了,反射没有任何可以产生新类的能力,也就顺理成章地找到了Javassist。

        在网上搜索到的大部分教程,都是针对Javassist的API进行一番讲解,但是最后,往往没有一个加载过程,而笔者模仿这些教程进行类的加载时,加载到的结果都是原来的类,并没有产生字节码被修改的内容。

        在经过一番探索后,笔者发现,网上的大部分教程中的最后一步,保存字节码,使用的均是writeFile的无参数重载,在查看其函数结构后发现,它还有一个String类型的重载,由于在Eclipse下,字节码储存的根位置并不是”.\\”而是”.\\bin”,而writeFile的另一个重载很可能是指定字节码根位置的参数,笔者进行一番更改后发现,果不其然。

 

下面将演示代码分享出来:

这是笔者项目的结构:


Editable.java:
package com.thrblock.javassist;
 
public class Editable {
      public void showInfo(){
             System.out.println("InfoDefault!");
      }
}


Main.java:
package com.thrblock.javassist;
 
import java.io.IOException;
 
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;
 
public class Main {
      public static void main(String[] args) {
             ClassPool pool = ClassPool.getDefault();
             try{
                    pool.insertClassPath(".\\bin");//设置根路径。(这里设置的根路径显然没被writeFile使用)
 
                    CtClass cc = pool.makeClass("com.thrblock.javassist.EditableChanged");//模拟Hibernate代理模式,我们创建一个新类
                    cc.setSuperclass(pool.get("com.thrblock.javassist.Editable"));//设置其父类
                    CtMethodcm = CtNewMethod.make("public void showInfo(){super.showInfo();System.out.println(\"CustomInsertHAHA!\");}",cc);//追加一个方法,注意它覆盖了父类中的方法。
                    cc.addMethod(cm);
 
                    cc.writeFile(".\\bin");//这里比较重要,空参的结果就是没有保存到eclipse字节码根路径里。
             }catch (NotFoundException | CannotCompileException | IOException e) {
                    e.printStackTrace();
             }
             try{
                    Class<?> cl = Class.forName("com.thrblock.javassist.EditableChanged");//加载我们的新类
                    Editableed = (Editable) cl.newInstance();//由于其继承与Editable类,这里和Hibernate里的load道理一样。
                    ed.showInfo();//调用方法。
             }catch (ClassNotFoundException | InstantiationException |IllegalAccessException e) {
                    e.printStackTrace();
             }
      }
}


打印结果:

Info Default!

CustomInsert HAHA!

其他注意事项:

由于我们是生成了一个类,如果这个类名和原类名一样,则会覆盖class文件,但是如果修改之前该class已经被JVM装入,则修改的部分不会生效,必须重启JVM。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值