Spring Frameworkの位置づけ
Springは、軽量かつオープンソースなJava EEフレームワークである。企業向けアプリケーションの開発において、複な依存関係を整理し、モジュール間の結合を和する仕組みを提供する。中でも、IoC(Inversion of Control:制御の反転)とAOP(Aspect Oriented Programming:面向切面プログラミング)は、Springの中核を占める2つの機能である。本記事では、IoCの本質とその内部動作について解説する。
IoCとは何か
IoCは「制御の反転」と訳され、オブジェクトの生成やライフサイクル管理、オブジェクト間の呼び出し関係をプログラマではなくフレームワーク側に委ねる設計思想を指す。Springでは、この方針に基づいてコンテナが各種オブジェクト(bean)を管理する。
IoCを導入することで得られる主な効果は以下の通りである。
- クラス間の結合度を下げ、保守性を向上させる
- オブジェクトの生成ロジックを集中管理し、重複を減らす
- テスト時のモック差し替えを容易にする
IoCの実現メカニズム
SpringのIoCコンテナは、以下の3つの技術を組み合わせて動作している。
- XML解析:設定ファイルに定義されたbean情報を読み込む
- ファクトリーパターン:コンテナがオブジェクト生成の責務を担う
- リフレクション:Class情報から動的にインスタンスを生成する
具体的な流れは次のようになる。まず、コンテナがXMLファイルを解析し、bean要素のclass属性などから対象クラスを特定する。次にリフレクションを利用してコンストラクタを呼び出し、インスタンスを生成する。こうして生成されたインスタンスはコンテナによって保持・管理される。
IoCコンテナの主要インターフェース
Springが提供するIoCコンテナの実装は、大きくBeanFactoryとApplicationContextの2系統に分類できる。いずれもbeanの管理機能を提供するが、用途や初期化タイミングに違いがある。
BeanFactory
BeanFactoryは、IoCコンテナの最も基本的なインターフェースである。Spring内部で使用されることを想定しており、原則としてアプリケーションコードから直接使用することは少ない。最大の特徴は遅延初期化(lazy initialization)であり、設定ファイルを読み込んだ時点ではbeanを生成せず、getBean()などで実際に必要になった時点で初めてインスタンス化する。
@Test
public void beanFactorySample() {
// 設定ファイルを読み込む段階では bean は生成されない
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new ClassPathResource("service-config.xml"));
// getBean() 実行時に初めてインスタンス化される
OrderService service = factory.getBean("orderService", OrderService.class);
service.process();
}
ApplicationContext
ApplicationContextはBeanFactoryを拡張したインターフェースであり、より高機能なコンテナ機能を提供する。国際化対応、イベント配信、AOP連携などが可能で、通常はこちらを利用する。ApplicationContextは、設定ファイルを読み込む段階ですべてのシングルトンbeanを生成する即時初期化(eager initialization)を採用している。
@Test
public void applicationContextSample() {
// 読み込み時点でシングルトン bean が生成される
ApplicationContext ctx = new ClassPathXmlApplicationContext("service-config.xml");
OrderService service = ctx.getBean("orderService", OrderService.class);
service.process();
}
ApplicationContextの代表実装クラス
ApplicationContextは複数の具象クラスを持つ。以下は代表的な2つである。
- ClassPathXmlApplicationContext:クラスパス上のXMLファイルを読み込む。通常、
src/main/resourcesなどに配置した設定ファイルを参照する際に使用する。 - FileSystemXmlApplicationContext:ファイルシステム上の絶対パスを指定してXMLファイルを読み込む。外部に配置された設定を参照する際に使用する。