irenka-overview
その2。
irenkaは、コンパイルタイム、ランタイム(クラスロード)などに、その読み込み処理に先立ってプログラム構造を調査し、必要であれば生成/ロードされるクラスを書き換えることを最初の目標とする。
例として、下記のようなクラスを考える。
@Hoge(Foo.class) public class Bar { @Foo public void method() { // .. } }
これを下記のように表せば、構造を破壊せずに同じことが書ける。
annotation ?hoge annotates Bar name Hoge value = Foo annotation ?foo name Foo annotates method() class ?bar name Bar extends java.lang.Object annotated Hoge declares method() method ?method name method params () type void declared in Bar annotated Foo
読み方は「
その後に annotates
上記では重複した情報が多すぎるため、余計な情報を少しだけ落とす。
annotation ?hoge annotates ?bar name Hoge value = Foo annotation ?foo name Foo annotates ?method class ?bar name Bar declares ?method method ?method name method()
この時点では、最初に挙げたクラス Bar をそのまま表す記述である。
これを、次のようなテンプレートから生成される、全てのクラスに対してマッチできるようにしてみる。
@Hoge(${annotation}.class) public class ${clazz} { #foreach($method in $class.getDeclaredMethod()) @${annotation} ${method} { // .. } #end }
すると、下記のようになる。
annotation ? annotates ?clazz name Hoge value = ?annotation annotation ?annotation annotates ?method class ?clazz declares ?method
このように、テンプレートより直感的(?)に、様々なクラスの構造を表現できるようになる。
コンパイルやクラスロードをする際に何らかのクラスを読み込んだ場合、読み込んだクラスの構造は記述された構造と比較される。比較をすると、?
下記を例に挙げると、
@Hoge(Foo.class) public class Bar { @Foo public void method() { // .. } }
先ほどの構造で宣言された変数は、次の値に束縛されることになる。
- ?clazz = Bar
- ?method = public void Bar.method()
- ?anotation = @Foo (annotates Bar.method())
この束縛された値を元に、様々な処理を行う。上記の例では、Bar, Bar.method() @Foo という情報を全て取得した状態で、何らかの処理を書けばよい。
詳しくは次回以降に。