Javassist是一個開源的分析、編輯和建立Java位元組碼的類庫。
Javassist是一個開源的分析、編輯和建立Java 位元組碼的類庫。是由東京工業大學的數學和計算機科學系的 Shigeru Chiba (千葉 滋)所建立的。它已加入了開放源代碼JBoss 應用伺服器項目,通過使用Javassist對位元組碼操作為JBoss實作動态AOP架構。 關于java位元組碼的處理,目前有很多工具,如bcel, asm。不過這些都需要直接跟 虛拟機指令打交道。如果你不想了解虛拟機指令,可以采用javassist。javassist是 jboss的一個子項目,其主要的優點,在于簡單,而且快速。直接使用java編碼的形式,而不需要了解虛拟機指令,就能動态改變類的結構,或者動态生成類。
轉自:http://yonglin4605.iteye.com/blog/1396494
我們需要建立的目标類,如下:
public class JavassistClass{
private String name="default";
public JavassistClass(){
name="me";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void execute(){
System.out.println(name);
System.out.println("execute ok");
}
}
如下為用javassist來建立類的代碼:
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtField.Initializer;
import javassist.CtMethod;
import javassist.CtNewMethod;
public class JavassistLearn{
public static void main(String[] args) throws Exception{
ClassPool cp=ClassPool.getDefault();
CtClass ctClass=cp.makeClass("com.slovef.JavassistClass");
StringBuffer body=null;
//參數 1:屬性類型 2:屬性名稱 3:所屬類CtClass
CtField ctField=new CtField(cp.get("java.lang.String"), "name", ctClass);
ctField.setModifiers(Modifier.PRIVATE);
//設定name屬性的get set方法
ctClass.addMethod(CtNewMethod.setter("setName", ctField));
ctClass.addMethod(CtNewMethod.getter("getName", ctField));
ctClass.addField(ctField, Initializer.constant("default"));
//參數 1:參數類型 2:所屬類CtClass
CtConstructor ctConstructor=new CtConstructor(new CtClass[]{}, ctClass);
body=new StringBuffer();
body.append("{\n name=\"me\";\n}");
ctConstructor.setBody(body.toString());
ctClass.addConstructor(ctConstructor);
//參數: 1:傳回類型 2:方法名稱 3:傳入參數類型 4:所屬類CtClass
CtMethod ctMethod=new CtMethod(CtClass.voidType,"execute",new CtClass[]{},ctClass);
ctMethod.setModifiers(Modifier.PUBLIC);
body=new StringBuffer();
body.append("{\n System.out.println(name);");
body.append("\n System.out.println(\"execute ok\");");
body.append("\n return ;");
body.append("\n}");
ctMethod.setBody(body.toString());
ctClass.addMethod(ctMethod);
Class<?> c=ctClass.toClass();
Object o=c.newInstance();
Method method=o.getClass().getMethod("execute", new Class[]{});
//調用位元組碼生成類的execute方法
method.invoke(o, new Object[]{});
}
}
javassist還有一個比較常見的用途是AOP,比如對一些類統一權重限過濾,加日志監控等等。
下面示例如何使用javassist來進行AOP攔截處理
我們對上面例子的JavassistClass類的getName()方法進行攔截前置處理
package com.taobao.relationrecommend.web.util;
import java.lang.reflect.Method;
import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
public class JavassistLearn{
public static void main(String[] args) throws Exception{
ProxyFactory factory=new ProxyFactory();
//設定父類,ProxyFactory将會動态生成一個類,繼承該父類
factory.setSuperclass(JavassistClass.class);
//設定過濾器,判斷哪些方法調用需要被攔截
factory.setFilter(new MethodFilter() {
@Override
public boolean isHandled(Method m) {
if(m.getName().equals("getName")){
return true;
}
return false;
}
});
//設定攔截處理
factory.setHandler(new MethodHandler() {
@Override
public Object invoke(Object self, Method thisMethod, Method proceed,
Object[] args) throws Throwable {
//攔截後前置處理,改寫name屬性的内容
//實際情況可根據需求修改
JavassistClass o=(JavassistClass) self;
o.setName("haha");
return proceed.invoke(self, args);
}
});
Class<?> c=factory.createClass();
JavassistClass object=(JavassistClass) c.newInstance();
System.out.println(object.getName());
}
}