package com.lj.javassist; import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod; public class Example01 { public static void main(String[] args) throws Exception { ClassPool pool=ClassPool.getDefault(); CtClass cc=pool.get("com.lj.javassist.User"); //byte[] b=cc.toBytecode(); CtMethod[] cms=cc.getDeclaredMethods(); for(CtMethod cm:cms){ cm.insertAfter("System.out.println(\"hello : \"+this.name);"); } Class clz=cc.toClass(); User u=(User) clz.getConstructor(new Class[]{}).newInstance(new Object[]{}); u.setName("alleni"); System.out.println(u.getName()); // cc.writeFile(); } }
这个代码的运行结果是:
hello : alleni
hello : alleni
alleni
这里不能执行cc.writeFile(), 否则会报错:
com.lj.javassist.User was pruned.
看了一下官方文档, 貌似要加入
cc.stopPruning(true);
这段文档在Frozen class那段,
The default value of ClassPool.doPruning is false.
To disallow pruning a particular CtClass, stopPruning() must be called on that object in advance:
因此只要把这段代码放在
ClassPool pool=ClassPool.getDefault(); CtClass cc=pool.get("com.lj.javassist.User"); //byte[] b=cc.toBytecode(); cc.stopPruning(true);
再次运行, 一切正常。
用FrontEnd反编译class文件, 可以看到如下代码
// Decompiled Using: FrontEnd Plus v2.03 and the JAD Engine // Available From: http://www.reflections.ath.cx // Decompiler options: packimports(3) // Source File Name: User.java package com.lj.javassist; import java.io.PrintStream; public class User { public User() { } public int getId() { _L2: return i; int i = id; System.out.println("hello : " + name); if(true) goto _L2; else goto _L1 _L1: } public void setId(int id) { _L2: return; this.id = id; Object obj = null; System.out.println("hello : " + name); if(true) goto _L2; else goto _L1 _L1: } public String getName() { _L2: return s; String s = name; System.out.println("hello : " + name); if(true) goto _L2; else goto _L1 _L1: } public void setName(String name) { _L2: return; this.name = name; Object obj = null; System.out.println("hello : " + this.name); if(true) goto _L2; else goto _L1 _L1: } private int id; private String name; }
虽然不知道那些if else语句和obj=null是什么玩意儿, 不过目标功能是实现了。
所有的方法都被加入了这句System.out.println(xxx);
Hibernate里面用到了Javassist,并通过这个东西实现了load查询方法的代理,和延迟加载。
具体内容以后再慢慢研究了。