お仕事スタイル
もう仕事から帰ってきてしまったのですが,日記なので(?)書いておきます.
- 黒のデニム・スーツ(BOSS 02-03AW)
- 白のスタンドカラーのシャツ(ISSEY MIYAKE MEN 02-03AW)
- 黒のストレートチップのシューズ(sergio rossi 03SS)
「恋するハニカミ!」
出てました,蛯原友里ちゃん! \(^o^)/
これってレギュラーって事ですか? 毎週エビちゃん見られるって事ですか? 素晴らしい!
まぁ,まさにお飾りというか添え物というか,そんな感じではあるのですが,それでも全然いいのです.
それにしても友里ちゃん,テレビ写りもよくなってきたというか,雑誌でのイメージと近くなってきた様子.今までテレビでは今ひとつの印象だったので心配していたのですが.今回はちゃんと素敵に見えました.できれば立ち姿も見たいので,エンディングは出演者みんな立って手を振るとかしていただきたい.
先週はせりふなかったらしいですが,今週はちょっとだけ声も聞けました.そうですか,水族館行ったことないのですか.上京してからずっと,CanCamやドラマの撮影で忙しかったのでしょうね.そのうちゲストの代わりに水族館デートなんていいんじゃないでしょうか.いずれ番組卒業なんて時には是非ともお願いしたい.
さぁ,これから毎週見るぞー.*1
*1:と,ここまで書いておきながら,この歳で書く内容じゃないよなーと気づく.心より恥じる.
里見へ+バグ
リンク元に上記検索結果からのリファがあったのでたどってみました.
id:makotanに負けている..._| ̄|○
なぜだ? なぜなんだぁー??
からさわぎスタイル
id:apiraさんのパクリで(^^;
明日のからさわぎに参加するスタイルを.見かけたZaizenerの方は一声かけてください.一緒に総回診をいたしましょう.
- インディゴっぽい染めのネイビーのカットソー(Margaret Howel 02-03AW)
- 明るいラベンダーのパンツ(ISSEY MIYAKE MEN 01SS)
- 白のスニーカー(JIL SANDER/Puma 02-03AW)
思ったより涼しかった場合はもうちょっと暖かい格好で出かけるかもしれません.心より恥じる.
Inter 0 - 1 Marseille
(;_;)
なぜ? なぜみんなそろって負ける? なぁケイ子,俺は間違っていたのか?
いいもんね,ホームで逆転だ!
Function と Procedure
近頃そこかしこで見かけるホット? それともクール? な話題,return null
.それを見ていて同じような話題を思い出したので久しぶりにB.Meyerの名著「オブジェクト指向入門」を開きました.っていうか第2版の翻訳は? 訳者の方,自分の著書は出版しているのに... 「この夏には出ます.」とおっしゃっていたのはもう3,4年も前だというのに... 無念だ.
B.Meyerは同書で,関数(function)と手続き(procedure)は明確に区別するべきだと主張しています.
- 関数(function)
- 戻り値がある.
オブジェクトの状態*1は変更しない. - 手続き(procedure)
- 戻り値がない.
オブジェクトの状態を変更する.
まったく逆なんですね.
関数というのは「問合せボタン」です.オブジェクトという機械についている問合せボタンを押すと,機械の状態を知ることができます.しかし,このボタンをいくら押しても機械の状態は変わりません.何度ボタンを押しても,確実に同じ結果を得ることができます.
手続きというのは「変更ボタン」です*2.このボタンを押しても機械の状態は分かりませんが,中ではガチャガチャとなにやら動いているようです.その後で「問合せボタン」を押すと,さっきまでとは違った結果を得ることになります.
原則として正しいのだと思います.特に「オブジェクト指向入門」で紹介されているEiffelというプログラミング言語には,表明という強力な概念が備わっています.表明はオブジェクトの状態やメソッドの引数が正しいことを検証するものですから,状態を変更してはいけません.つまり,関数は利用できますが,手続きを利用してはいけません.この二つを明確に区別することで,ある値を検証するために呼び出したメソッドが思わぬ副作用を持っていたなんていう無用のトラブルを避けることができるわけです.素晴らしい.
確かに素晴らしいのですが,現実はなかなかこの原則を全面的に受け入れられなかったりもします.例えば同書に出てくる乱数の場合.
Javaではこうですが,
Random randomGenerator = new Random(); int rand = randomGenerator.nextInt();
nextInt()
は乱数を返すと同時にRandom
の状態を変更しています.これは原則に反します.よって,次のようでなくてはなりません.
Random randomGenerator = new Random(); randomGenerator.next(); int rand = randomGenerator.intValue();
うーむ.あなたはこれを受け入れられますか?
同じくスタックの場合.
Javaだとこうですが,
Object item = stack.pop();
pop()
はスタックの一番上の要素*3を取り除いて,それを返しています.これは原則に反します.よって,次のようでなくてはなりません.
Object item = stack.top(); stack.pop();
うーむ.うーーーむむ.あなたはこれを受け入れられますか?
さて,この原則と return null
を同時に踏みにじっている例として,Map#remove(Object)
をあげることができます.このメソッドは,Map
に引数をキーとするマッピングが含まれていればそのマッピングを取り除き,マッピングの値を返します.マッピングが含まれていない場合はnull
を返します.
Object item = map.remove(key); if (item != null) { ・・・ }
いけませんねー.次のようでなくてはなりません.
if (map.containsKey(key)) { Object value = map.get(key); map.remove(key); ・・・ }
うーむ.うーーーむむ.うーーーーーーーむむむ.あなたはこれを受け入れられますか?
正しい原則であっても,それを常に押し通すことが適当とは限らない,ということなのでしょう.もちろん,原則を知らないとか無視するのとは訳が違います.正しい原則をよぉく理解して,その上で適当な場合には原則を破ることもいとわない.そんな風にありたいものです.
さて自分は? 原則を知らないことが多いかも... 心より恥じる.
静かな一日
ようやく,よーやく! 静かに一日を過ごすことが出来ました.なにもなし.はぁー,こんなにトラぶったのはじめてだよ.やはり歳は取りたくないものです.心より恥じる.
さ,これで次のお仕事に取りかかれます.今度はガラリと変わって開発環境の整備.現在は VisualAge for Java Enterprise Edition + CVS で開発しているものを,WebSphere Studio Application Developer + ClearCase*1 に変更します.実はアプリケーションサーバ(WebSphere Application Server)は一足先にバージョンアップしていて,VisualAgeが対応しているバージョンとはズレているのです.それどころか,VisualAgeはJDK1.1相当で本番環境はJDK1.3というありさま.なので,早いところこのズレをなくさないといけないわけです.しかーし,9000以上のクラス,10000以上のJSPがあって,並行して開発中の案件も多いときているため,なかなか大変なのです.なにより,あまり楽しい作業ではないのでやる気Null
っぽいところが課題です.
*1:びっくり,キーワードになってるよ!
Spring Framework 入門記 AOPその11 ProxyFactoryBean再訪
順番だと次は「5.4. Advisors in Spring」なのですが,とても短いので軽ーく.Advisorは,Aspectをモジュール化するもので,たいていはAdviceとPointcutを組み合わせたものです.だそうです.直訳風です.以上!
ということで「5.5. Using the ProxyFactoryBean to create AOP proxies」へ進みます.苦しんだ「AOPその1」でこの連載^H^H日記を救ってくれたのがこの5.5節でした.ようやく戻ってきましたよ.
さて,すでに学習したとおり,ProxyFactoryBean
はSpringのAOP機能を実現しているFactoryBean
であり,このAOP編で疑いなく最も重要な存在です.たぶん.
ProxyFactoryBean
もSpringのコンテナから見るとただのBeanですから,プロパティを設定することができます.ProxyFactoryBean
は,次のプロパティを持っています.これまでの学習で,次のプロパティを使用してきました.
target
- AspectをWeavingされるBeanを指定します.
interceptorNames
- Advice(Interceptor)やAdvisorであるBeanの名前を指定します.
それ以外にも,ProxyFactoryBean
は,次のプロパティを持っています.
proxyTargetClass
boolean
のプロパティで,true
にするとinterface
ではなく,class
をターゲットにします.これは,java.lang.reflect.Proxy
ではなく,CGLIBを使ってProxyを作成することを意味します.Proxyをターゲットクラスとして扱うことができます.java.lang.reflect.Proxy
を使用したProxyの場合,それをターゲットクラスとして扱うことはできません(ターゲットクラスのインスタンスではない).interface
を通してのみ利用できます.optimize
boolean
のプロパティで,true
を設定すると積極的に最適化されたProxyを作成するとのことです.よく分かっていなければ使うなとのこと.僕はいい子なので使わないことにします.無念だ.frozen
boolean
のプロパティで,true
に設定すると,ProxyFactoryBean
が構成された後(コンテナにDependency Injectionされた後)は,ProxyFactoryBean
を変更しないことを意味します.デフォルトはfalse
です.
通常は,XMLの定義ファイルに書かれた通りにProxyFactoryBean
を設定した後,プログラマティックに設定を更新するようなことはあまりないと思います.よって,たいていはtrue
に設定してもいいのではないかと思います.exposeProxy
boolean
のプロパティで,true
に設定すると,ProxyをThreadLocal
から取得できるようになるとのこと.そのThreadLocal
は,AopContext
から取得できるそうです.って「5.5. Using the ProxyFactoryBean to create AOP proxies」には書いてあるのですが,現実にはAopContext#currentProxy()
で取得するのかな? このドキュメント,結構実装と食い違っている記述が多いんで,油断大敵です.
それで,AopContext
は抽象クラスなのですが,そのインスタンスはどこから入手できるのでしょう? うーん,もっと先に出てくるのかな? とりあえず保留.無念だ.aopProxyFactory
ProxyFactoryBean
が使用するProxyのファクトリであるProxyFactory
を設定します.これを切り替えることで,まったく異なったAOP Proxyを使用できるようになるというわけです.ふーん.あまり必要になって欲しくない感じですが,万が一の時にはいろいろ好きなようにできるということですね.proxyInterfaces
Class
の配列のプロパティで,Proxyが実装するinterface
を指定します.このプロパティが設定されない場合は,CGLIBを使用してターゲットの派生クラスとしてProxyが作成されます.
このプロパティが設定されると,java.lang.reflect.Proxy
を使用したDynamic Proxyが作成されます.singleton
FactoryBean
おなじみのboolean
のプロパティです.false
に設定されると,コンテナからインスタンスを取得するたびに新たなProxyが作成されます.ステートフルにmixinを組み込む場合に使えるとか.でもそれってどんな場合?
ソースを見ると他にもプロパティらしきものがあるようなのですが,ドキュメントに登場するのは以上です.
これまでの学習では,proxyInterface
を指定したことがなく,常にCGLIBによるProxyを使ってきたので,これを試してみることにしましょう*1.
まずはinterface
を用意します.
package study; public interface Foo { void print(); }
その実装クラスを作成します.
package study; public class FooImpl implements Foo { private String text; public String getText() { return text; } public void setText(String text) { this.text = text; } public void print() { System.out.println(text); } }
そして定義ファイル.<bean>
要素以下のみです.
<bean id="foo" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <bean class="study.FooImpl"> <property name="text"><value>FOO</value></property> </bean> </property> <property name="proxyInterfaces"><list><value>study.Foo</value></list></property> <property name="interceptorNames"><value>debugInterceptor</value></property> </bean> <bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"> </bean>
ごらんのとおり,proxyInterfaces
プロパティにFoo
を指定しています.
そして実行用のクラスです.中ほどのみ.
Foo foo = (Foo) context.getBean("foo"); foo.print(); FooImpl fooImpl = (FooImpl) foo;
まずはinterface
で取り出して,print()
メソッドを呼び出しています.その後,FooImpl
にキャストしています.
さぁ,実行!!
Debug interceptor: count=1 invocation=[Invocation: method=[public abstract void study.Foo.print()] args=null] target is of class study.FooImpl] FOO Debug interceptor: next returned java.lang.ClassCastException at study.Main.main(Main.java:16)
というわけで,ちゃんとAspectが適用されていること,Foo
というinterface
では扱えるものの,FooImpl
というターゲット本来のclass
としては扱えないことが分かります.
なお,proxyInterfaces
プロパティを指定していても,proxyTargetClass
プロパティにtrue
を設定すると,FooImpl
にキャストすることが出来ました.CGLIBによるProxyが作成されるからですね.
なお,CGLIBを使ったProxyの場合,ターゲットでfinal
宣言されているメソッドにはAspectを適用できないそうです.なるほど.こういった点を踏まえて,両者を使い分けようということですね.この入門記のようなお遊びではともかく,実際の開発で使うなら,きっちりinterface
を定義してやりたいところです.その場合はjava.lang.reflect.Proxy
を使うことができるので,その方がよさそうな気がします.
ということで,全然たいした事をしていませんが,今日はここまで.次は「5.6. Convenient proxy creation」に進みます.