-Threadlocalize
SeasarConのセッション中デモでやらなかったサンプル
@Threadlocalize private Foo field1 = new Foo(); field1 = var1; field1.bar();
こういう風に、ユーザーコードの中で用意したメタアノテーションで修飾されたフィールドがあったとしたら、
private ThreadLocal<Foo> field1 = new ThreadLocal<Foo>(new Foo()); field1.set(var1); field1.get().bar();
と書き換えちゃうプロセッサの例。
public class ThreadLocalizeProcessor { /** * @when {@link ThreadLocalize} in self.annotations * tl = {@link ThreadLocal} */ public void processDecl(CtClass<ThreadLocal<?>> tl, CtField<?> self) { CtType<?> type = self.getType(); // フィールドの型を取得 CtClass<?> ptl = tl.getParameterized(type); // ThreadLocalのタイプ引数にセット type.substitute(ptl); // フィールドの型宣言を書き換える CtExpression<?> init = self.getInitializer(); // 初期化子を取得 if (init.exists()) { // 初期化子を引数に取るThereadLocalのコンストラクタ init.substitute(ptl.newInvocation(init)); } else { // 引数無しのThreadLocalのコンストラクタをぶち込む init.substitute(ptl.newInvocation()); } } /** * @when self.leftHandSide = field; * field = {@link CtField} // fieldは引数リストに無いためJavadoc内で型制約をつける * {@link ThreadLocalize} in field.annotations * set = {@link ThreadLocal#set(Object)} // メソッド定義を引っ張ってくる */ public void processAssgin(CtAssignment<?, ?> self, CtMethod<?> set) { CtMethodInvocation<?> methodInvocation = set.newInvocation(self.getRightHandSide()); // フィールドアサインを置き換え methodInvocation.getQualifier().substitute(self.getLeftHandSide()); // あ、「Qualifier」ってなじまないかな?メソッド呼び出しの主体のこと。 self.substitute(methodInvocation); } /** * @when self = field * field = {@link CtField} // fieldは引数リストに無いためJavadoc内で型制約をつける * {@link ThreadLocalize} in field.annotations * get = {@link ThreadLocal#get()} // メソッド定義を引っ張ってくる */ public void processUse(CtExpression<?> self, CtMethod<?> get) { CtMethodInvocation<?> methodInvocation = get.newInvocation(); methodInvocation.getQualifier().substitute(self); // フィールド参照を置き換え self.substitute(methodInvocation); } }
はじめのprocessDecl()でフィールド定義を冒頭例示のように書き換え、processAssgin()でフィールドへ値を設定している箇所全てをThreadLocal#set()に書き換えます。そして、processUse()でフィールドを読み出している箇所全てをThreadLocal#get()利用にするものです、これでコード全部です。ほらね、簡単でしょ?