Java: ダイナミックプロキシ

スクリプト言語の方面からは不評なJavaですが、その1つにはリフレクションが使いにくいとかいうのがあるそうです。
そういうことは、ダイナミックプロキシのことを知ってから言うのも悪くないと思うので、簡単な紹介を。
http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/reflection/proxy.html
この機能を使えば、smalltalkの#doesNotUnderstandやrubyのmethod_missingのような機能が(インターフェースを宣言しなければならないという制限はあるものの)実現できます。
たとえば、次のようにすることで、インターフェースを引数に渡すと、呼び出されたメソッドのメソッド名を標準出力に出力するだけのオブジェクトを生成して返します。この例では、java.sql.Connectionのオブジェクトを作って、適当にメソッドを呼び出しています。

import java.lang.reflect.*;
import java.sql.*;

public class Main {
  public static void main (String[] args)
  throws Exception
  {
    Connection conn = PrintProxy.newInstance(Connection.class);
    conn.prepareStatement("SELECT * FROM FOO");
    conn.getMetaData();
    conn.rollback();
    conn.close();
  }
}

class PrintProxy implements InvocationHandler {
  private PrintProxy () {}
  public Object invoke (Object proxy, Method m, Object[] args)
  throws Throwable
  {
    System.out.println(m.getName() + "()");
    return null;
  }
  @SuppressWarnings("unchecked")
  public static <A> A newInstance(Class<A> intf) {
    return (A) java.lang.reflect.Proxy.newProxyInstance
      (PrintProxy.class.getClassLoader(),
       new Class[] {intf},
       new PrintProxy());
  }
}

出力結果。

$ java Main
prepareStatement()
getMetaData()
rollback()
close()

この機能、ほとんど知られていないらしく、google:java ダイナミックプロキシで検索しても239件しかヒットしません。