Guice2.0 beta 紹介記事の翻訳(2)
原文:IBM Developer : Sorry, that page no longer exists
訳1:Guice2.0 beta 紹介記事の翻訳(1) - 山本大の日記
Guiceによる基本的なインジェクション (Basic injection with Guice)
DIが設計に価値を加えることと、フレームワークを使うと日常的な開発が簡単になることについて、あなたを説得したいと思います。
では、@Injectとモジュールを手始めに、Guiceに飛びこんでいきましょう。
クラスに@Inject-edが必要だとGuiceに教える (Tell Guice you want your class @Inject-ed)
「FrogMan」と「GuiceでのFrogMan」の違いは、@Injectアノテーションです。リスト5はアノテーションを付けたFrogManのコンストラクタです。
リスト5. @InjectされたFrogMan(FrogMan has been @Injected)
@Inject public FrogMan(Vehicle vehicle) { this.vehicle = vehicle; }
※訳注 @Injectにハイライト
エンジニアの仲には、@Injectアノテーションをクラスに記述するのを嫌がる人もいます。
彼らは全体的にDIフレームワークに依存しない事のほうを好むのです。これは、もっともなことです。しかし私はそれでは納得できません。依存性があることに比べればアノテーションはかなり軽いものです。@Injectタグは、Guiceにクラスを生成するように命令したときにだけ意味をもちます。もし、FrogManを生成するようにGuiceに命令しなければ、アノテーションはコードの動きにまったく影響ありません。アノテーションは、Guiceがクラスの生成に参加することを示す良い手掛かりを提供します。しかしながら、それはソースレベルでの記述を必要とします。もし、あなたがコントロールできないソースのアノテーションが、オブジェクト作成にGuiceを使用することを苦しめるならば、Guiceには代替のメカニズムがあります(後述するプロバイダーメソッドサイドバーへの別用途を参照)。
Tell Guice which dependency you want
ここまでで、Guiceはあなたのヒーローが乗り物を必要とすることを知りました、どういった乗り物が提供されるかをしることが必要です。リスト6にはモジュールが記載されています。これは、どの実装クラスがどのインターフェイスに設定されるのかをGuiceに対して知らせるために使う特別なクラスです。
リスト6.ヒーローモジュールで乗り物に対してフロッグモービルを紐付けする。(The HeroModule binds Vehicle to FrogMobile)
public class HeroModule implements Module { public void configure(Binder binder) { binder.bind(Vehicle.class).to(FrogMobile.class); } }
モジュールは、一つだけのメソッドを持つインターフェイスです。Guiceがモジュールに渡すBinderは、Guiceに対してどのようにオブジェクトを生成するかを伝える手段を提供します。binderのAPIはドメイン特化言語(domain-specific language)の書式を取っています(参照)。これは、たとえば「bind(X).to(Y).in(Z)」のような表現力豊かなコードを書くことができる小型言語です。binderがどのようなことができるのかを照会するサンプルは、この記事を進めていくとより多く見ることができます。バインディングを生成するどの呼び出しでも、Guiceがインジェクションを要求することで解決します。
バインドするための各呼び出しはバインディング、およびバインディングのセットを作成します。そして、それらをGuiceがインジェクション要求を解決するのに使用します。
Injectorによるブートストラップ(Bootstrap with an Injector)
次にInjectorクラスを使ったGuiceの起動コードを見てみましょう。典型的にはプログラムの一番初めの方でInjectorを生成します。
これは、Guiceにできるだけたくさんのオブジェクトを生成させるためです。リスト7は、Injectorを使った「ヒーローの冒険」を開始するメインプログラムのサンプルです。
リスト7 Injectorを使ったアプリケーションの起動コード(Bootstrapping your application with an Injector)
public class Adventure { public static void main(String[] args){ Injector injector = Guice.createInjector(new HeroModule()); FrogMan hero = injector.getInstance(FrogMan.class); hero.fightCrime(); } }
Injectorインスタンスを取得するためには、GuiceクラスのcreateInjectorメソッドを呼び出します。
createInjectorにモジュールのリストを引き渡せば、モジュールの設定を利用することができます。
(この例ではモジュールは1つだけですが、"邪悪なる者(evildoers)"を設定した"悪党モジュール(VillainModule)"などを追加することもできます。)
ひとたびInjectorを手に入れれば、getInstanceメソッドに".class"を渡すことによって、オブジェクトを取り出したいときに取り出すことができます。
(抜け目のない読者は、Guiceに対してFrogManのことを伝える必要がないということに気づいていることでしょう。また、コンクリートクラスを問い合わせた場合、そしてそのクラスが@Injectコンストラクタか、または引数の無いパブリックコンストラクタを持っているなら、Guiceはバインドを呼び出す必要なしにそれを生成するということがわかります。)
明示的に問い合わせることは、オブジェクトを構築してGuiceから取得する第1番目の方法です。
しかしながら、起動ルーチンの外側でこのようなことをやりたくないと思うかもしれません。
より良くて、簡単な方法は、Guiceに依存性や、依存性の依存性や、その他諸々を注入させることです。
(いわば、"亀が地球を支えている"ってやつです参照)。
これははじめのうちは混乱するように思えるでしょうけれど、しばらく使ってれば慣れてきます。
リスト8のサンプルは、フロッグモービルが燃料を注入されるところを表しています。
リスト8. フロッグモービルが燃料を受け取る(The FrogMobile accepting a FuelSource)
@Inject public FrogMobile(FuelSource fuelSource){ this.fuelSource = fuelSource; }
これはFrogManを取得するときにGuiceが"燃料(FuelSource)"と"フロッグモービル(FrogMobile)"を生成し、それから最後にFrogManを生成することを表しています。あなたのアプリケーションがたった1度だけInjectorとやり取りするにもかかわらずです。
もちろん、いつでもアプリケーションのメインルーチンのコードを書き換えられるというわけではないでしょう。
たとえば多くのWebフレームワークでは、自動的に"actions"や"templates"やその他のものをスタートポイントとして生成して提供してくれます。
通常、フレームワークのプラグインや独自の手書きのコードを使わずとも、Guiceを組み込むための場所を見つけることができます。(たとえば、GuiceプロジェクトはStruts2のためのプラグインをリリースしています。これはStruts Actionの設定をGuiceにさせるためのものです。(参照))