Programming-Spring特集第3弾。Programming(以下AOP)について書きます。AOPとは?共通的な機能を後から付け加える仕組みです。具体的に言うと、ロギングキャッシングセキュリティ認証などの共通的に利用される機能をビジネスロジックから切り離して、後から横断的に追加できるような仕組みのことです。Adviceの例を書きます。Adviceとは、AOPの用語で追加する共通処理のことです。何をやっているかは以下のサンプルを見れば一目瞭然です。}}ポイントとなる設定ファイルの書き方を説明します。AOPの設定は、aop:config要素の中に書きます。aop:aspectの中に、Aspectの設定を書きます。(処理を埋め込む場所)です。ちなみに(処理を埋め込む場所)のことをPointcutと呼びます。Pointcutと覚えておくとよいです。設定ファイルの説明に戻ります。簡単に設定箇所を纏めると以下のようになります。aop:pointcut要素のid属性にPointcutのIDを、expression属性に共通処理を埋め込みたい場所を正規表現で書きます。aop:before要素のpointcut-ref属性に使用するPointcutのIDを、method属性に1.で指定したBeanのメソッド名を書きます。(このメソッドがAdviceになる)aop:after要素もaop:before要素と同様に書きます。実行結果は、以下のようになります。crying.このようにAOPを利用すると、任意の処理を任意の場所に後から埋め込むことができます。Adviceの他にもAdviceはあります。以下にAdviceの種類を纏めます。処理をメソッドの実行前に追加したい場合。処理をメソッドの実行後に追加したい場合。処理をメソッドの実行前後に追加したい場合。処理をメソッドが正常終了した後に追加したい場合。処理をメソッドが異常終了した(例外がスローされた)後に追加したい場合。このように、どのタイミングでAdviceを挿入したいかに応じて様々な種類のAdviceを使うことができます。それぞれのAdviceの使用方法はSpringSource.orgのreferenceを参照してください。まとめDIがオブジェクト間の依存性を外部に掃き出し、それを後から注入する機能だと考えると、AOPはオブジェクトと共通機能の依存性を外部に掃き出し、それを後から注入する機能だと考えることができます。AOPを使うことで機能追加/変更に強いソースコードを書くことができます。Injection(以下DI)の機能について書きます。bracelet"DIとは?いい例が浮かばなかったのですが、例えば以下のようなプログラムを考えてみてください。}}何かに投資するInvestorクラスがあって、投資するために複雑な計算をします。その計算にGoodCalculatorというクラスを使おうというシチュエーションです。上のように書いてしまうと、InvestorクラスはGoodCalculatorクラスが無いと使用できません。InvestorクラスはGoodCalculatorクラスに依存しています。一般にクラスが別のクラスに依存していると、クラスの独立性が低いため、再利用しにくい独立したテストが行い辛いというデメリットがあります。Investorの例に戻ります。今使われているGoodCalculatorより優秀なBetterCalculatorが開発されて、BetterCalculatorを使おう。なったらどうでしょう?GoodCalculatorを使っている場所をすべて書き直さなければなりません。使われている場所が1ヶ所だけならいいですが、何10箇所、何100箇所もあったら大変です。}}こうすると、Investorは中身がどのように実装されているかは知りませんが、Calculatorインターフェースを実装した何らかのクラスを使うことになります。GoodCalculatorがBetterCalculatorに変更されても、そもそもGoodCalculatorというクラス名を直接ソースコード上に書いていないので変更は生じません。BetterCalculatorがcalculateメソッドを実装していなければ、Adapterデザインパターンを使ってCalculatorインターフェースを実装するクラスを作ればいいでしょう。Frameworkに具体的なクラスを注入してもらいましょう。このように、ソースコードからクラス間の依存性を取り除き、外部から依存性を注入することをDIと呼びます。以下では、コンストラクタによるDIsetterによるDIの2種類のDIを説明します。コンストラクタによるDI全章の後半で導入したように、コンストラクタで使用するCalculatorを渡す場合は以下のようにすればDIができます。ポイントはXML設定ファイルのinvestorのbean定義のconstructor-arg要素の部分です。この部分でコンストラクタに渡す具体的なクラスを指定しています。注入する具体的なクラスを変えたい場合は、この部分を変更するだけでOKです。</bean></beans>setterによるDI同様にsetterを利用して、具体的なクラスを注入することができます。</bean></beans>setterを利用したDIでは、まず引数なしコンストラクタでInvestorクラスをインスタンス化した後、setterでcalculatorを設定しています。使用するcalculatorを変えたい場合は、investorのbean定義のproperty要素のref属性を変更すればOKです。どちらを使うべきか?コンストラクタを使用したDIとsetterを使用したDIを説明しました。「で、どっち使えばいいの?」という疑問が浮かぶと思いますが、必須の依存性を注入したい場合はコンストラクタによるDI、オプショナルな依存性を注入する場合はsetterを使用したDI、という使い分けをするのが一般的です。必要に応じて両方同時に使うことも可能です。Frameworkについて、基本的な機能を簡単に紹介します。Programmingの3つの機能を3回のpostに分けて書きます。オブジェクトの生成から書きます。</bean></beans>XMLファイルにBeanのidとクラスのマッピングを記述します。使用者はidを指定して対応するクラスのオブジェクトを生成します。普通にnewすればいいんじゃない?と思う人もいるかもしれませんが、上記のようにSpringが提供するコンテナからオブジェクトを生成することで、DI/AOPといった機能が使えるようになります。フィールド値の設定オブジェクトを生成するときにフィールドの初期値を設定出来ます。idをつけることで区別できます。XMLのproperty要素内でフィールドの設定をしていますが、ここで設定するフィールドには必ずsetter(この例の場合はPerson#setMessage)を定義しなければいけません。(JavaBeansなので当然ですが。</bean></beans>と、このように太郎くんと花子さんを作れます。BeanのスコープBeanを生成するときに、そのスコープを設定することができます。singletonprototyperequestsessionglobal-session3.-5.はWebアプリケーションに特化したものなので、ここでは1.と2.のみを説明します。</bean></beans>scope="singleton"のところに注目です。名前から想像がつくように、scopeをsingletonにすると同一のidを持つBeanはアプリケーション上で一つしか作られません。context#getBeanは毎回同じインスタンスの参照を返します。実行結果は>Goodbye!>Goodbye!となります。ちなみにデフォルトのスコープはsingletonです。scope属性を明記しなかった場合、そのBeanのスコープはsingletonになります。次に、prototypeを試してみます。先ほどと同様の例でscope属性のみをprototypeに変更すると、実行結果は>Goodbye!>Hello!になります。スコープをprototypeにすると、毎回異なるインスタンスが生成されます。コールバック関数の指定Beanが生成されたとき/破棄されるときに、何か処理をしたい場合はコールバック関数を指定することができます。</bean></beans>XMLファイルのbean要素のinit-method属性、destroy-method属性にて、コールバックしたい関数を指定することができます。mainメソッド内でAbstractApplicationContext#registerShutdownHookを呼んでいますが、これを呼ぶことで確実にBeanが破棄されdestroy-methodで指定した関数が呼ばれるようにしています。PrototypeまえおきPrototypeパターンの勉強をしました。書籍だけで大まかなイメージは掴めましたが、「複雑な過程を経てインスタンス生成されるものを簡単に作れる」という例があると、より分かりやすいと思います。まとめプロトタイプと呼ばれるオブジェクトをコピーすることで、複雑な過程を経てインスタンス化されるオブジェクトの生成を簡単にすることができる。コピーされたオブジェクトは、プロトタイプとは独立しているので、必要に応じてフィールドの内容を変更することができる。書籍には「複雑な過程を経てインスタンス生成されるものを簡単に作れる」という例が無くて具体的なイメージが湧かなかった。参考サイト[1]を見て複雑な過程(もしくは時間のかかる処理)を経て作られるインスタンスのイメージが掴めた。その他cloneメソッドとCloneableインターフェースに関して学んだ。copyでよいのか注意する。Stage"キーボードの設定を変えました。HUDの無効化デフォルトでは、Altキーを押すとHUDが立ち上がります。Altキーを押す度にウィンドウが開いてフォーカスが移り面倒なので、このサイトを参考にHUDを無効化しました。右Altキーの設定やっぱり右Altキーは欲しいです。いうことで、以下の手順で変換キーを右Altキーに割り当てました。コマンドラインにxevと入力する。変換キーを押すと、変換キーのkeycode(100)が表示される。UNIX2012年8月17日金曜日GETとPOSTの違いGETとPOSTの違いについて勉強しました。GETデータはURLに含まれる。idempotentな(永続的な効果をもたらさない、副作用をもたらさない)処理を行うときに使うことが推奨されている。⇒データを取得するときに使用する。body部分に含まれる。idempotentではない処理を行うときに使うことが推奨されている。⇒データのソート、更新、商品の注文、Emailの送信など。実用的な違い/留意点GETはサーチエンジンのクローラーに踏まれる可能性があるので、副作用のある処理をGETで処理すると、不用意にデータを消去されたり、更新されたりする可能性がある。GETリクエストに対するレスポンスはキャッシュできる(※)場合が多い。POSTリクエストに対するレスポンスがキャッシュされることはほとんどない。GETはURLをブックマーク保存できる。GETはURLにデータが載るので、Webサーバやプロキシサーバーのログに残る。リンクで他ページに遷移したときにRefererのところにも載る。⇒パスワードなどのセンシティブな情報を送る場合はGETは避けるべき。GETにはASCII文字以外を含めない方がいい。(原則上は扱えないが、実用上は扱える。)マルチバイト文字をクエリーに含む検索処理の場合は、POSTを使う方が(idempotent=GETの基本精神に反するが)ベター。GETはPOSTより送信できる情報量が少ない。ブラウザの「戻る」ボタン⇒POSTは警告を上げる。GETはそのまま遷移。(※)ちなみにキャッシュはいろいろな種類があって、ブラウザーキャッシュプロキシーキャッシュゲートウェイキャッシュ(リバースプロキシー)などがあります。まとめ基本的には、データのREAD処理の場合はGETを使い、CREATE/UPDATE/DELETE処理の場合POSTを使えばよいと思います。あとはセキュリティの観点からセンシティブな情報を送信する場合はPOSTを使うべきです。(3)java.util.Stackのソースを読みました。実装は非常にシンプルで分かりやすかったです。気になったところだけ以下にまとめます。Vector<E>Eはジェネリクスの型変数の宣言。クラス宣言部を見て分かるように、StackはVectorを継承しています。synchronizedStackでは以下のメソッドが定義されています。pushpoppeekemptysearchStackから連想する処理は一通り実装されています。気になったのは、synchronized。赤字のメソッドのみsynchronized句が指定されています。synchronizedする/しないの違いが気になったので、考えてみました。1);}まずpopですが、3行目と6行目の間で別のスレッドがpopを実行した場合に、ArrayIndexOutOfBoundsExceptionが発生する可能性があります。これを防止するためにオブジェクトにロックをかけていると考えられます。同様にpeekの場合も2行目と7行目の間に別スレッドからpopを実行されるとArrayIndexOutOfBoundsExceptionが発生する可能性があります。searchは少し違います。ArrayIndexOutOfBoundsExceptionがthrowされそうな箇所は見当たりません。-1;}searchの仕様は、対象のオブジェクトがStack内に存在すればそのindexを1-basedで返します。存在しなければ-1を返します。..)が返される可能性があります。これを防止するためにsynchronizedを設定していると考えられます。pushにはsynchronizedが指定されていないので、searchの実行中に別スレッドからpushが実行される可能性はあります。(スレッドがオブジェクトのロックを気にするのは、synchronizedブロックを実行しようとする場合のみなので。)しかし、これは返されるindexが1インクリメントされるだけなので問題はないです。synchronizedされていないpush、emptyについては上記で見てきたような問題とは無関係ですし、特に他に同期させるべき場面も思い浮かばないので、無くてよいのかなぁという感じです。簡単に必要ないと言いましたが、本来は、他の処理から割り込ませないような場面がないことと、他のsynchronizedが付いている処理を邪魔する可能性がないことを保証した上で、synchronizedは付けなくていいという結論を出さないといけないんですよね。マルチスレッドを考慮したクラス設計は難しいですね。(2)java.lang.Booleanのソースを読みました。おもしろかったところだけ簡単にまとめておきます。Class.getPrimitiveClass("boolean");でbooleanのラッパークラスのClassインスタンスを取得します。Class.getPrimitiveClassメソッドの定義を見ると、以下のようにnative修飾子がついています。以外の言語で記述されてコンパイルされていることを示します。いうことで現段階で深堀りするのはやめておきます。serialVersionIDシリアライズするときに使うもの。クラスの仕様が変更されていたら不都合があるので、この番号でクラスの仕様が等しいことを確認するようです(http://www.mkyong.com/java-best-practices/understand-the-serialversionuid/)。hashCodeこれはもともとObjectクラスで定義されており、Booleanクラスでオーバーライドされています。java.util.HashMap(コメントより抜粋)らしいです。取得したプロパティ値をBooleanにキャストして返します。プロパティはこんなのがあるらしいです。http://docstore.mik.ua/orelly/java/fclass/ch10_02.htm上記のページに載っているプロパティを見てもいまいち使い方が分からなかったので、値がtrueになるプロパティがもともと定義されているかどうか以下のコードを書いて調べました。開発者がアプリ上で設定した値の真偽を調べるために使われるものだと考えられます。SingletonまえおきSingletonです。説明が分かりやすく、かつ、例題もどのような場面で使うのかをしっかり抑えている内容だったため簡単に理解できました。まとめそのクラスのインスタンスがシステム上で1個しか存在しないことを保証する。コンピュータそのものを表現したクラス、システム設定を表現したクラス、ウインドウシステムを表現したクラスなどが使用対象となる。なしその他コンストラクタをprivateにするというのは大事なポイント。意図を理解していない開発者に対象オブジェクトを普通にnewされると困ったことになってしまうので。フィールドが初期化されるタイミングも重要。マルチスレッドに関する問題がおもしろかった。synchronizedについて勉強しなおした。*としてみましたが、ヒットせず。TODOとかやってみました。いやこれだとカレントディレクトリ配下にTODOという文字列を含むファイルorサブディレクトリがないか検索してるだけだ。findでヒットしたファイルをgrepの引数として渡してあげる方法はないんだろうか・・・。xargsを使えばよさそうです。TODOでやりたいことができました。argumentsの略らしいです。RunTimeのソースコードを読んでいくことにした。動的な解析をするための環境を整えた。ソースの取得ソースコードが無かったので、以下のコマンドで取得した。これで、/usr/lib/jvm/java-7-openjdk-commonにsrc.zipというzipファイルができる。ここにソースファイルが格納されている。このsrc.zipのソースをコンパイルして、jarにまとめたものが/usr/lib/jvm/java-7-openjdk-i386/jre/lib/rt.jar。開発環境構築~/codereading/javaというディレクトリを作成し、そこにsrc.zipを解凍。rt.jarをコピーして持ってきて、jarファイルの中身を取り出して、bin配下に格納した。最終的に以下のようなディレクトリ構成にした。MANIFEST.MF/usr/lib/jvm/java-7-openjdk-i386/jre/lib/rt.jarの実体は削除して、上記のrt.jarへのシンボリックリンクにした。これで、ソースコードを適当にイジってコンパイルしてjarファイルを更新すれば、JVMがロードするクラスの内容も変わるはず。Invoked.");}コンパイル。binjarファイルも更新。../rt.jarテスト用のクラスを書く。Postsmemset()とmemcpy()恥ずかしながら、Cのmemset()とmemcpy()を今まで使ったことがなかった。みたいな話を聞いたことがあったので、「あーじゃ要らない機能なんだー。editorialに投稿された解答がmems...便利なPythonライブラリ(5)retryデコレータつけるだけで、リトライしてくれるという便利ライブラリ。失敗するかもしれない不安定な関数に@retryをつけると成功するまで実行してくれる。ret...S3のファイルを一般公開するAWSのS3のファイルを一般公開する方法について説明します。2つの場合に分けて説明します。本番中ゴリ押し解を思いつくには思いついたのだが、C++でマルチスレッドの処理を書いたことが無くて、ごにょごにょやってるうちにタイムアップとなってしまった。C++...C#入門(9)Action、Func、Predicateの違いAction、Func、Predicateについて簡単に整理しておく。メソッドへのDelegate。メソッドへのDelegate。スライド区間に対するクエリ処理の種類とそれに対するアルゴリズムをいくつか紹介します。「スライド区間」の定義ですが、窓関数のようなものを想像してください。まではコンピュータの力を使って正多面体をt色以下で塗るパターン数を数えていました。今回は手計算で計算してみようと思います。そのためにはまず回転を表す対称群をうまく列挙するために回転軸について考える必要があります。見聞きする木の用語を整理しておく。節点vから最も離れた節点をwとする。w)の長さをvの離心数と呼ぶ。記号で表すときは、ε(v)と書く。使って遊んでみました。いった便利な機能を提供してくれるテストフレームワークです。repor...キャッシュヒット率の測定perfというツールを使ってキャッシュヒット率を測定してみた。キャッシュの影響なんてたかが知れていると甘くみていたら、痛い目るので要注意。知らない用語がちらほらあったので、簡単にまとめておく。