の続き。
今回はGoogle Guice。設定ファイルが一切なく、コードによって設定を記述するというのが売りです。Generics等J2SE 5.0の機能を使い、型が安全なようになっています。型があわないなど記述ミスがあればちゃんとコンパイルエラーになってくれますし。
EJB3、Springともにインターフェースの型のみでのインジェクトをしました。今回はGuiceも同様の記述の仕方でいきます。インターフェースの型のみで判断する場合、実装はひとつでなければならないので、そういう書き方をGuiceでもしてみました。
まずはインターフェース。実装クラスを記述することによってインターフェースと実装クラスの関連を省略する書き方です。現実的に実装を差し替えるということは少なく、ほとんどの場合がインターフェースと実装は1:1です。そういう前提でなければEJB3やSpringもああいう書き方は不可能でした。したがってほとんどの場合問題ないことになるはずです。所詮動作そのものに影響をしないアノテーションなため、定義を自前で書けばなんということはないという感じで。
@ImplementedBy(HelloImpl.class) public interface Hello { String getMessage(String name); }
現実的な線としてこの書き方はありだと思います。もちろん、これも強要するのではなくて、ユーザーに使用の判断を任せています。各自の考え方で使用するかどうか適切に処理してください。この書き方だとIDEの機能を使い、アノテーションの属性部分をCTRL+クリックで実装に飛べるために非常に開発が容易となっています。インターフェースをふんだんに使ったシステムで構築した場合、実態がどこにあるのかが非常に分かりにくくなってしまいます。ましてそれを自動化するDIコンテナならばなおさらのことです。
続いて実装。これはEJB3やSpringと違い、アノテーションが一切つかないのを理解してください。
public class HelloImpl implements Hello{ public String getMessage(String name) { return "はろー"+name+"さん"; } }
使用する場合。
package guicetest; import 省略 public class NewMain { @Inject Hello hello; public void print(){ System.out.println( hello.getMessage("Guice") ); } public static void main(String[] args) { Injector injector = Guice.createInjector(); NewMain main = injector.getInstance(NewMain.class); main.print(); } }
インジェクトしたい箇所に@Injectをつけるだけ。インターフェースと実装が1:1であることが分かりきっている場合非常にシンプルです。
Guice#createInjectorは可変長引数ですので、0個でもいいわけです。
ポイントはインスタンスそのものの取得の場合、型によって判断をします。SpringやEJBのJNDIは名前、つまりStringによる判断なのに対してGuiceは型なのです。一応文字列の属性つきアノテーションを別途用意することによって同様のことは可能になりますが、それはあくまでもオプションであり、基本となる考え方の違いだと思われます。
Guiceは非常にシンプルで型に強く、ライブラリも小さく、起動も実行も高速です。Guiceそのものは他のフレームワークとの連携機能はほとんど用意されていませんが、シンプルなだけに既存のフレームワークと組み合わせるのは容易なはずです。特にDIコンテナ以外でインスタンスの生成をしてもらい、そのインスタンスに注入をするという使い方が得意なGuiceは、JavaSE環境では他のDIコンテナを圧倒するといって間違いないでしょう。
起動が軽い、フットプリントが小さいというメリットははJavaSEだけに限りません。Webアプリでも開発時にストレスが少なく、型が強いために非常にバグが少なくなりやすいということでもあり、設定をコードで書くために、技術者にとって数あるDIコンテナの中でもっとも挙動が分かりやすく、一目瞭然だったりします。覚えることが最も少ないコンテナです。
つまり、Guiceで開発する一番のメリットは数あるDIコンテナの中でもっともストレスフリーな環境だということに尽きると思います。