Spring3のアノテーションによるDIを試みる
例によってふと何かアプリケーションをつくりたくなって、であればこの間エンドユーザ側(?)に徹していたDIフレームワークについてもうすこし理解を深めてみよう、ということでSpring3を使ってみることにしました。この記事はそのときの依存性解決のメモ。
DIにもいろいろなアプローチがあり、Springフレームワークにおけるその「品揃え」もいろいろあるようですが、今回はJavaクラス&アノテーションベースのDIを使用することにしました。
これは下記のようにJavaコードによりコンフィギュレーションを実行するものです。
1. コンフィギュレーション - ビーン定義
@Configuration public class AppConfig { @Bean public MyService myServiceA() { return new MyServiceAImpl(); } @Bean public MyService myServiceB() { return new MyServiceBImpl(); } }
2. コンフィギュレーション - 自動結合
public class MyServiceAImpl(){ @Autowired private MyServiceB serviceB; }
3.DIの実行とビーンの取得
public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class); MyServiceA a = ctx.getBean(MyServiceA.class); MyServiceB b = ctx.getBean(MyServiceB.class); }
Javaコードによるコンフィギュレーションのための依存性解決
問題はこの依存性注入フレームワークを使うための依存性解決でした、、、
Mavenなどの依存性解決・ビルド実行システムを使えば話は簡単なのでしょうが、今回は手作業です。
まず、Spring Frameworkそのものは、こちらのページの「SpringSource Community」からダウンロードしました。(SpringSource Tool Suiteやその他のプロダクトに紛れている印象が…。)
ダウンロードしたzipファイルを展開し、distディレクトリから下記のjarを取り出して、EclipseのJavaプロジェクトにコピー。クラスパスに追加しました。
- org.springframework.core-3.0.6.RELEASE.jar
- org.springframework.beans-3.0.6.RELEASE.jar
- org.springframework.context-3.0.6.RELEASE.jar
- org.springframework.asm-3.0.6.RELEASE.jar
- org.springframework.expression-3.0.6.RELEASE.jar
さらにこれらのjarが依存する外部プロジェクトのjarを見繕ってきます。(従来はこれらの依存するクラス群がSpring自体に同梱されることもあったようですが。)
- commons-logging-1.1.1.jar
- cglib-2.2.jar
- asm-3.3.jar
- asm-commons-3.3.jar
この4つを探すのにとても時間がかかりました。こういったことを心得ている人には大したこともないのでしょうが、AntのビルドスクリプトやMavenのpomをあさって、依存するjarとそのバージョンを特定するのに1・2時間かかりました…。
XMLベースのコンフィギュレーションとJavaベースのコンフィギュレーション
Springその他のフレームワークの普及によって、DIというとやはりXML形式のコンフィギュレーションファイルが想起されます。
実際、記述的に依存性の解決をできるXML形式は、ロジックと依存性解決の役割分担をこれ見よがしに明示しますし、完全に状態を排除した(すべき)サービスクラスはデフォルトコンストラクタにより初期化されるので、これで十分です。とりわけコンポーネントの数が多数に上るとき、XMLの説明的で一覧的な記述形式が適しているように思います。
けれどもXMLは柔軟性がありすぎること、またJavaという別の言語について記述することから来る、ミスの起こりやすさ(実行時例外として顕在化する)や、デフォルトコンストラクタを持たない(あるいはそれだけでは初期化に不十分な)コンポーネントを初期化するための記述の煩雑さなどの、問題もあります。
これに対してある程度の事前検証を期待できる方法として(これとて完全ではないわけですが)、SpringではJavaクラスとアノテーションの組み合わせによってDIを行う方法が提供されています。(以前、記事を書いたGuiceも同種の試みです。)