クラスを操作してみる
では、実際に簡単なクラスを用意して操作をしてみることにしましょう。ここでは、以下のようなごくシンプルなBeanクラスを作成し、これを操作してみることにします。
package jp.tuyano.jasample;
public class TestBean {
public String testfield = "helo";
public void test(){
System.out.println(testfield);
}
}
これをコンパイルしクラスファイルを作成しておきます。このクラスファイルに、直接フィールドとクラスを追加してみることにしましょう。
package jp.tuyano.jasample;
import java.io.IOException;
import java.lang.reflect.*;
import javassist.*;
public class JavassistSample {
public static void main(String[] args) {
ClassPool pool = ClassPool.getDefault();
try {
CtClass cc = pool.get("jp.tuyano.jasample.TestBean");
// フィールドの追加
cc.addField(new CtField(CtClass.intType,"addfield",cc));
// メソッドの追加
String mstr = "public void addmethod(){System.out.println(\"add this method.\");}";
cc.addMethod(CtMethod.make(mstr,cc));
cc.writeFile();
} catch (NotFoundException e) {
e.printStackTrace();
} catch (CannotCompileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
printTestBean();
}
// TestBeanのクラスとフィールドを出力する
public static void printTestBean(){
Class c = TestBean.class;
System.out.println("[class]");
System.out.println(c.getName());
Method[] methods = c.getMethods();
System.out.println("[methods]");
for(Method m:methods){
System.out.println(m.getName());
}
Field[] fields = c.getFields();
System.out.println("[fields]");
for(Field f:fields){
System.out.println(f.getName());
}
}
}
これを実行すると、TestBeanのクラスファイルを書き換えて「addmethod」というメソッドと「testfield」というフィールドを追加します。追加後にTestBean内のメソッドとフィールド名を書き出していますので、ここで確認をしてみてください。これらのフィールドとメソッドが追加されているはずです。
実行するとコンソールにTestBeanクラス内のメソッドとフィールドが書き出される。 |
では、簡単な流れを説明しておきましょう。実際に操作を行なっているのはmainメソッドの部分になります。
ClassPool pool = ClassPool.getDefault();
まず、ClassPoolを取得します。これは、ClassPool.getDefaultでデフォルトのClassPoolが得られますので、通常はこれを使います。
CtClass cc = pool.get("jp.tuyano.jasample.TestBean");
続いて、TestBeanのCtClassを取得します。これはClassPoolのgetメソッドを使います。ここで取り出すクラス名を引数として渡せば、そのクラスのCtClassインスタンスが得られます。このとき、完全修飾名でクラスを指定するようにしておきましょう。
cc.addField(new CtField(CtClass.intType,"addfield",cc));
CtClassが得られたら、クラスを修正に進みます。最初にフィールドを追加します。フィールドは、CtFieldインスタンスとして扱われます。これは、new CtFieldとして作成します。引数には、フィールドの種類を示す値(CtClass内のクラスフィールドを使って指定します)、フィールド名、組み込み先のCtClassをそれぞれ渡します。
String mstr = "public void addmethod(){System.out.println(\"add this method.\");}";
cc.addMethod(CtMethod.make(mstr,cc));
続いてメソッドの作成です。メソッドは、あらかじめメソッドの内容をStringとして用意しておきます。そして、CtMethodのmakeメソッドで追加をします。引数には、メソッドの内容を示すStringと組み込み先のCtClassを渡します。
cc.writeFile();
修正が終わったら、最後にCtClassのwriteFileを呼び出してクラスファイルを書き換えます。これで修正した状態にクラスファイルが変更されます。