メソッドを再定義した後、元に戻す

まだ試せていないが、javassist を素直に使った方が良いみたいだ。独自にやろうとソースを見てみたが・・・見ても分からない orz

-- 追記 試してみた --

package test;
class Person {
  /** */
  private String name_ = null;
  /**
   * @param name
   */
  public Person(String name) {
    name_ = name;
  }
  /**
   * @return
   */
  public String getName() {
    return name_;
  }
}

この Person クラスの getName の戻り値を変えてみる

ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.get("test.Person");
CtMethod method = ct.getDeclaredMethod("getName");
// name_ の代わりに "modifiled" を返す
method.insertBefore("return \"modified\";"); 
Class clazz = ct.toClass();
Person person = new Person("hogehoge");
System.out.println(person.getName()); // => modified

CtClass#toClass を呼び出せば、そこから Class#newInstance とかしなくても良いみたい。その後は新しいオブジェクトを生成して Person#getName を呼び出しても全て "modified" が返るようになる。

JUnit で Mock オブジェクトとして使いたかったんだけど、、、あるテストでメソッドの内容を変更してしまうと、テストを行うクラスが異なっていても全て変わってしまう。変わって欲しくないところまで変わっちゃうんだなぁ・・・
使用する特定のクラスだけで変更されるのがベストなんだけどなぁ。

試しにメソッド呼び出し後に

ct = cp.get("test.Person");
ct.toClass();

としてみたら

Caused by: java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader): attempted duplicate class definition for name: "test/Person"

って出た。やっぱ元にもどせないのか。