Lakers 85 - 102 Kings

(;_;)
先月完勝したキングスに完敗です.コービー8点... 無念だ.
シャック10点5リバウンド... 心より恥じる.
うー,最後の最後で今ひとつだなー.これで地区優勝も無理っぽい.ホームコードアドバンテージなしで大丈夫か? ここに来てウルブズやスパーズが勝ち続けてるし...
今年もプレーオフは激戦必至のようです.

お仕事スタイル

  • 黒のシルクのカットソー(JIL SANDER 03SS)
  • 黒のコットンのパンツ(JIL SANDER 03SS)
  • 黒のスニーカー(TOM FORD FOR GUCCI 02-03AW)

今日は夏日だとか天気予報で言っていたのでかなり薄着です.夜は大丈夫か?
id:monajiroさんが「春もののアウターは着れる期間が短い」というようなことを書かれていましたが,まさに!ですね.4月中旬にして早くもアウター不要です.
さらに,長袖のカットソーも着れる期間が短いんですよね.すぐに半袖になっちゃうから.がんばって着れないわけではないですが.
今日のカットソーはメッシュ状のシルク素材のもので,最初はスケスケじゃないかと思ったもの.でも試着したら全然そんなことなくて,タイトな身ごろに超細い袖がとっても気に入ってます.


23:45追記 やっぱり夜は寒かったです.もうちょっとの間,アウターがあってもよさげ.

里見へ

この手紙を持って,「Seasarのからさわぎ@東京」レポーターとしての最後の仕事とする.まず,女性参加者が皆無で絶望死した僕の病態を解明するために,若かりし頃ぶいぶい言わせたid:masataka_k教授に病理解剖をお願いしたい.以下に,女性勧誘についての愚見を述べる.
女性の参加を促す際,第一選択はあくまでid:higayasuoさんのイケメンをアピールすべしという考えは今も変わりはない.しかしながら現実には,先日のからさわぎがそうであるように,女性の参加者が皆無であるという虚しいイベントがしばしば見受けられる.その場合には,広報担当たるid:habuakihiroさんの日記でアピールする必要があるが,タイトルの色を変えたとはいえ,いまだ満足のいく成果には至っていない.むしろちぐはぐでちゃんちゃらおかしいね.これからの「Seasarのからさわぎ」の飛躍はid:habuakihiroさん以外の日記の発展にかかっている.
僕は,id:manholeさんの日記がその一翼を担える数少ない日記であると信じている.能力を持ったものには,それを正しく行使する責務がある.id:manholeさんには女性参加者の勧誘に挑んでもらいたい.遠くない未来に,女性参加者のいない「Seasarのからさわぎ」がこの世からなくなることを信じている.ひいては僕の屍を病理解剖の後,君の研究材料の一石として役立てて欲しい.
女性のいない「からさわぎ」は生ける師なり!
なお,自ら最年長クラスの独身男性であるものが女性とめぐり合う願いがかなわず,id:skimuraさん主催の合コンに手を上げられぬまま死す事を... 心より恥じる
財前五郎


勝手にIDを使わせていただいた皆様,申し訳ありません.m(__)m
一部大変失礼な表現をしてしまい,本当に本当に申し訳ありません.m(__)m m(__)m m(__)m

Spring Framework 入門記 AOPその12 My ProxyFactoryBean

からさわぎでSeasarにノックアウトされたので,今日からSeasar入門記です.
嘘です.ごめんなさい.日記的にはより複雑でより難しくて日本語の情報が少なくて頼るところが少ないSpringの方が何かと好都合なので,これからもSpring入門記です.*1
与太話はともかく,今回は「5.6. Convenient proxy creation」です.
SpringのAOPのかぎを握っているのはProxyFactoryBeanです.間違いない.こいつがターゲットにAspect(Interceptor,Advisor)を適用したProxyを作ってくれます.S2と異なり,SpringのコンテナはAOPに一切タッチしないため,すべてはこのProxyFactoryBeanがお膳立てをしてくれるわけです.
そのProxyFactoryBeanですが,使い勝手はいまいちです.何がいまいちかというと,Interceptor/Advisorはそれを実装したBeanの名前を指定するのですね.当然,そのBeanは別途定義する必要があります.なので,ちょっとデバッグ用にトレース出したいよ,という場合でもこうなっちゃいます.

<bean id="foo" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target">
        <bean class="study.Foo"/>
    </property>
    <property name="interceptorNames"><value>debugInterceptor</value></property>
</bean>
<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor">
</bean>

そりゃまぁ,たいした量じゃないことは分かるんですけどね.でも,Proxy本体とばらけて定義するのがやな感じ.それから,DebugInterceptorは特にプロパティもなくて簡単に使えるからいいけれど,トランザクションやセキュリティの類だと超面倒になりそう.
そんな時には,オリジナルのProxyFactoryBeanを作っちゃえ! っていうのがSpring流.らしいです.
これってもしかするとAnt風かも.Antもいろいろなタスクを標準で用意してくれていますが,それで足りなかったりビルドファイルの記述が大変になる場合はオリジナルのタスクを作ったりしますよね.makeなんかと比べると,いちいちコード書いてコンパイルして... っていう作業が多くなりがちです.なんとなく,そんな感じ.
そういう例の一つとして,TransactionProxyFactoryBeanが説明されています.これは,いわゆるコンテナ管理のトランザクションを実現するためのものです.実際には,そのためのAspect(Interceptor)としてTransactionInterceptorが用意されているのですが,これを普通にProxyFactoryBeanでWeavingしようとするととっても大変!! みたい.
そんな場合にTransactionProxyFactoryBeanを使うと,それがもう少し簡単に使えるよ! っていうことらしいんですね.
もう一つの例として,EJBがあげられています.あまり詳しくは書かれていないのですが,どうやらSimpleRemoteStatelessSessionProxyFactoryBeanとかっていうProxyFactoryBeanがあって,これを使うと普通のBean呼び出しをEJB呼び出しに変えてしまえるような,そんなAspectをWeavingしてくれるそうです.なるほどなるほど.


それでですね,ちょっと話が逸れるのですが,その辺のコードを眺めていてちょっと気づいたことがあります.こういう場合には,「AOP その10」で学習したIntroduction Adviceとか,「Seasarのからさわぎ」でまさたかさんが説明してくださったような「interfaceインスタンス化するAspect」なんていうのが有効に使えそうです.まさたかさん,宴会でそれはCrosscutting Concernとは違うのではないか,そういうのはOOPでの実装継承のようなもので,AOPの使い方を間違えているのではないか,と主張してしまいましたが,間違っていたのは私のようです.心より恥じる.


さぁ気を取り直して,そんな便利なTransactionProxyFactoryBeanを使ってみようか? なんて一瞬思ったのですが,ここでのテーマはトランザクションではありません.ちょっと便利なProxyFactoryBeanがテーマなのです.それなら,ちょっと便利なProxyFactoryBeanを作ることが日記の使命! ということで,意味はありませんがおなじみのDebugInterceptorをWeavingするProxyFactoryBeanを作ってみましょう.クラス名は当然DebugProxyFactoryBeanです.本来はDebugTraceProxyFactoryBeanにしたいところですが,Interceptorの名前がDebugInterceptorなので仕方がありません.無念だ.

それで,その作り方を知りたいのですが,この「5.6. Convenient proxy creation」にはろくな解説がありません.EJBを置き換えるとか与太話はいいからそっちの説明してくれよ.嘘です,ごめんなさい,与太話だなんて思ってません,本当です,失礼しました.m(__)m


ともかくですね,ドキュメントは参考にならなさそうです.そんな場合は,ソースを見られるのがオープンソースのいいところ.しくしくしく.しょうがねー,見るか.とりあえず,TransactionProxyFactoryBeanを参考にします.
オリジナルのProxyFactoryBeanを作るには,とりあえずProxyConfigというクラスを継承すればいいようです.名前から想像するに,Proxyを構成できるってことですよね.うんうん.ちょっと意外ですが,ProxyConfigは抽象クラスではありません.なので,派生クラスで実装しなければならないメソッドがあるわけでもなさそうです.じゃあなぜこれを実装するのか? その謎は後でProxyを作るところで発覚しました.が,説明は面倒なのでコードを見たほうが早いと思うので,いっちゃいましょう.

package study;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.aop.framework.ProxyConfig;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.framework.support.AopUtils;
import org.springframework.aop.interceptor.DebugInterceptor;
import org.springframework.aop.target.SingletonTargetSource;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;

public class DebugProxyFactoryBean extends ProxyConfig implements FactoryBean, InitializingBean {
    private Object target;
    private Object proxy;
    //InitializingBean
    public void afterPropertiesSet() {
        if (this.target == null) {
            throw new AopConfigException("Target must be set");
        }

        DebugInterceptor interceptor = new DebugInterceptor();
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.addInterceptor(interceptor);
        proxyFactory.copyFrom(this);  //ここ注目
        proxyFactory.setTargetSource(new SingletonTargetSource(target));
        proxyFactory.setInterfaces(AopUtils.getAllInterfaces(this.target));
        this.proxy = proxyFactory.getProxy();
    }
    //FactoryBean
    public Object getObject() throws Exception {
        return this.proxy;
    }
    public Class getObjectType() {
        if (this.proxy != null) {
            return this.proxy.getClass();
        }
        else if (this.target != null) {
            return this.target.getClass();
        }
        else {
            return null;
        }
    }
    public boolean isSingleton() {
        return true;
    }
    //setters/getters
    public Object getTarget() {
        return target;
    }
    public void setTarget(Object target) {
        this.target = target;
    }
}

実際にProxyを作成するのは,afterPropertiesSet()です.この,FactoryであるところのBeanに対するプロパティの設定が終わったところでコンテナから呼び出される,InitializingBeanのメソッドですね.そこでちょっとしたエラーチェックだけ行った後,Proxyを作成しています.
Proxyを作成するには,ProxyFactoryクラスを使います.このクラス,実はProxyConfigのサブクラスです.こいつにいろいろ設定するわけですが,その一部の情報は同じくProxyConfigのサブクラスであるこいつ自身,すなわちDebugProxyFactoryBeanからコピーします.ちょっと分かりにくい感じですが,実はProxyConfigは,aopProxyFactoryoptimizefrozenといった,前回学習したプロパティを持っています.ということで,定義ファイルでこのDebugProxyFacotryBeanに設定したプロパティを,実際にProxyを作成するProxyFactoryにコピーするということなんですね.なるほどー.? なるほどか?
DebugProxyFactoryBeanProxyFactoryのサブクラスにすれば,そんなわけのわからない事をしなくても済むような気がするのですが,面倒だしまぁよしとしましょう.無念だ.
ともかくですね,ProxyFactoryを作って,DebugInterceptorを追加して,なんかそれらしいことをすればいいようです.心より恥じる.
ともかくオリジナルの,この私のオリジナルのProxyBeanFactoryが完成しました.後は使うべし.
ということで,定義ファイルを用意します.<bean>要素以下のみ.

<bean id="foo" class="study.DebugProxyFactoryBean">
    <property name="target">
        <bean class="study.Foo"/>
    </property>
</bean>

うおぉぉぉっ! これがSpringのXMLか?*2 これまでと全然違って超シンプル.やったね!
省略しますが,Fooにはprint()というメソッドがあります.実行用のクラスでは,それを呼び出します.
ということで実行!!!

Debug interceptor: count=1 invocation=[Invocation: method=[public void study.Foo.print()] args=[Ljava.lang.Object;@18166e5] target is of class study.Foo]
Spring must die.
Debug interceptor: next returned

\(^o^)/

*1:でも,これはSpringネガティブキャンペーンの一環だったりするのは内緒である.

*2:一応「これが俺の肺か?」なのでZaizener.

Making of Spring Framework 入門記

そういえば「Seasarのからさわぎ@東京」で何人かの方から(ほんの2,3人ですが)同じような質問を頂いたのを思い出しました.「本当に入門しながら書いてるの?」みたいなの.本当なんですよ,これが.
一見似たようなことをやっているようでも,まさたかさんのS2チュートリアルとはずいぶん違います.まさたかさんの場合,S2は一通り理解しておられるにもかかわらず,世のため人のためS2のためにチュートリアルを書いておられるわけですね.ありがたや.
ところが私は違います.日記のネタにするためにのみSpringを学習し,単にその記録を書いているわけです.人のためではなく,純粋に自分の日記のためです.心より恥じる.
それでまぁ,だいたいこんな流れで書いてます.
たいていは平日の夕方,職場のチャイムが鳴ってから入門記を書き始めます*1.「Spring Reference Documentation」のその日の学習部分をさらりと眺めてから日記の出だしを書いて,話の流れに合わせてドキュメントを詳細に読んだり,必要に応じてソースを見たりします.それからサンプルを書いてうまく動いたら日記にコピペします.
サンプルを書いていて勘違いに気づいた場合は何もなかったように日記を修正します(苦笑).ついでにうけ狙いで脚色することもまれにありますが,あまり面白いことは思いつかないのでそう多くはありません.無念だ.
で,日記に書いた後はドキュメントを先読みしないようにします.先走って読んじゃうと翌日以降,日記に書く気力がなくなりそうなので.ちょっと見出しを確認しておくくらいですね.
そんな訳ですから,なかなか学習ペースが上がりません.実際の開発で使うのなら,こんなにのほほんとやってられませんよね.でもいいのです.日記ですから.

*1:小心者なのです.