よく知られているように、Spring フレームワークではコンテナー・ベースの構成を使用して IoC (Inversion of Control: 制御の反転) パターンすなわち DI (Dependency Injection: 依存性注入) パターンを実装しています。Spring では従来、アプリケーションのコンテキスト XML ファイルを使用した XML ベースの構成を使用することで Bean の依存関係を管理しています。このファイルはアプリケーションにとって外部ファイルであり、そのアプリケーションに対する Bean および Bean の依存関係に関する定義を保持しています。XML ベースの構成は使いやすくて便利ですが、Bean および Bean の依存関係を定義する方法には、「Java ベースの構成」と呼ばれる方法もあります。XML の場合とは異なり、Java ベースの構成ではプログラムによって Bean を管理することができ、そのためにはさまざまなアノテーションを使用します。この記事では、Java ベースの構成を用いた例について、XML による従来の構成方法と比較しながら説明します。従来の方法と比較することで、この Java ベースの構成についてよく理解できるようになるはずです。この記事では Java ベースの構成の基本的な使い方を以下のステップで説明します。
- @Configuration アノテーションと @Bean アノテーションの概要
- AnnotationConfigApplicationContext を使って構成クラスを登録する方法
- Web アプリケーションを構成する方法
- Bean のライフサイクル・コールバックとスコープを実装する方法
ここでは、オンライン大学の「Create Course (コース作成)」の例を取り上げます。このコース (course) 作成のプロセスでは、トピック、つまりモジュール
(module) も作成し、各トピックにはさまざまな課題 (assignment) を含めることも可能です。そこで、Course、Module、Assignment という 3 つの Bean を作成します。Course Bean は Module Bean を参照し、その Module Bean は Assignment Bean への参照を保持します。
@Configuration アノテーションと @Bean アノテーションの概要
理想的なシナリオでは、アプリケーション・コンテキストを表現する XML で Bean を定義します。以下のコードは Create Course という例の Bean を定義するコンテキスト XML を示しています。
リスト 1. Bean を定義する XML
<beans> <bean id="course" class="demo.Course"> <property name="module" ref="module"/> </bean> <bean id="module" class="demo.Module"> <property name="assignment" ref="assignment"/> </bean> <bean id="assignment" class="demo.Assignment" /> </beans> |
上記の XML は、Spring で Bean を構成する場合に作成される典型的な XML です。この XML では Course Bean を定義し、Course Bean は Module Bean
を参照しています。そして、Module Bean は Assignment Bean を参照しています。ここで、この XML をやめ、この XML と等価な Java
コードを作成します。上記のように規定された Bean を、Java ベースの構成を使用して定義します。この XML を、Bean
を構成するためのプラットフォームとして動作する Java クラスで置き換えます。このクラスの名前を AppContext.java としましょう。以下のコードは AppContext クラスを示しています。
リスト 2. Bean の定義を含む AppContext 構成クラス
@Configuration
public class AppContext {
@Bean
public Course course() {
Course course = new Course();
course.setModule(module());
return course;
}
@Bean
public Module module() {
Module module = new Module();
module.setAssignment(assignment());
return module;
}
@Bean
public Assignment assignment() {
return new Assignment();
}
}
|
上記のコードを見るとわかるように、今度は Java ベースの構成の一部として、Bean がプログラムで定義されています。この場合の AppContext クラスは、先ほどの XML とまったく同じように構成クラスを表します。これは @Configuration
アノテーションを使用することで実現されています。@Configuration アノテーションはこの
AppContext クラスの上に配置されており、Spring コンテナーに対し、このクラスが Bean
の定義と依存関係を含む構成クラスであることを伝えています。@Bean アノテーションは Bean を定義するために使われており、Bean をインスタンス化して Bean の依存関係を設定するメソッドの上に配置されています。このメソッドの名前はデフォルトで、Bean の ID、つまり名前と同じです。このメソッドの戻り型は Spring のアプリケーション・コンテキストに登録された Bean です。この Bean のセッター・メソッドを使用して依存関係を設定すると、コンテナーはそれらの依存関係を呼び出し、関連付けを行います。Java ベースの構成はアノテーション・ベースの構成と見なすこともできます。
AnnotationConfigApplicationContext を使用して構成クラスを登録する方法
XML による従来の方法では、ClassPathXmlApplicationContext クラスを使用して外部の
XML コンテキスト・ファイルをロードします。しかし Java ベースの構成を使用する場合には AnnotationConfigApplicationContext クラスがあります。AnnotationConfigApplicationContext クラスは ApplicationContext インターフェースの実装の 1
つであり、アノテーションを付けられた構成クラスを登録するために使用することができます。この場合の構成クラスは @Configuration アノテーションを使って宣言された
AppContext です。このクラスを登録すると、@Bean
アノテーションが付けられたメソッドによって返されるすべての Bean の型も登録されます。以下のコードは AnnotationConfigApplicationContext クラスの使い方を示しています。
リスト 3. AnnotationConfigApplicationContext を使用して AppContext クラスを登録する
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppContext.class);
Course course = ctx.getBean(Course.class);
course.getName();
}
|
上記のコードを見るとわかるように、AppContext 構成クラスは AnnotationConfigApplicationContext
コンストラクターに渡されることで登録されています。こうする代わりに、このコンテキスト・クラスの register メソッドを使用して AppContext 構成クラスを登録することもできます。その方法を示したものが以下のコードです。
リスト 4. AppContext クラスを登録するための別の方法
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppContext.class)
}
|
構成クラスを登録すると、@Bean
アノテーションが付けられたメソッド名が自動的に登録され、それによってその構成クラスに対応する Bean、つまり Course、Module、Assignment も登録されます。すると、getBean メソッドを使用して当該する Bean を取得し、その Bean のビジネス・メソッドを呼び出すことができます。つまり、これを見るとわかるように、Java ベースの構成クラスの作成は非常に簡単であり、この構成クラスを Spring コンテキストに登録する方法も非常に簡単です。次のセクションでは Webアプリケーションで Java ベースの構成を使用する方法について説明します。
通常、Spring Web アプリケーションを構成する場合には、Web デプロイメント記述子ファイルである web.xml の中で外部 XML
コンテキスト・ファイルへのパスを指定し、XmlWebApplicationContext
コンテキストを使用します。XMLWebApplicationContext は Web
アプリケーションがデフォルトで使用するコンテキスト・クラスです。以下のコードに示す web.xml
内の要素は、ContextLoaderListener リスナー・クラスによってロードされる外部 XML コンテキスト・ファイルを指しています。
リスト 5. 外部 XML コンテキスト・ファイルを使用する web.xml
<web-app> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>sampleServlet</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> </servlet> ... </web-app> |
今度は、AnnotationConfigApplicationContext クラスを使用するように、上記の web.xml のコードを変更します。XmlWebApplicationContext は Spring がデフォルトで Web
アプリケーションに使用するコンテキスト実装であることを思い出してください。そのため、このコンテキスト・クラスを web.xml ファイル内で明示的に指定することはありません。今度は Java ベースの構成を使用するので、Web
アプリケーション用に構成する際、web.xml ファイル内で AnnotationConfigApplicationContext クラスを指定する必要があります。上記のコードを変更すると以下のようになります。
リスト 6. AnnotationConfigApplicationContext を使用するように変更された web.xml
<web-app> <context-param> <param-name>contextClass</param-name> <param-value> org.springframework.web.context. support.AnnotationConfigWebApplicationContext </param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value> demo.AppContext </param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>sampleServlet</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextClass</param-name> <param-value> org.springframework.web.context. support.AnnotationConfigWebApplicationContext </param-value> </init-param> </servlet> ... </web-app> |
変更された上記の web.xml は、今度はコンテキスト・パラメーターとサーブレット要素の一部として AnnotationConfigWebApplicationContext
コンテキスト・クラスを定義しています。コンテキストを構成する場所として、今度は AppContext 構成クラスが指定されています。これは簡単でした。次のセクションでは Bean のライフサイクル・コールバックとスコープの実装方法について説明します。
Bean のライフサイクル・コールバックとスコープを実装する方法
Java ベースの構成を使用して Bean のライフサイクルも管理することができます。@Bean は initMethod と destroyMethod という 2
つの属性をサポートしており、この 2 つの属性を使用してライフサイクル・メソッドを定義することができます。ライフサイクル・メソッドは Bean
がインスタンス化される時に、または破棄される直前に、コンテナーによって呼び出されます。ライフサイクル・メソッドはコンテナーに呼び出されるため、コールバック・メソッドとも呼ばれます。@Bean アノテーションによって登録される Bean は、JSR-250 の一部としての標準的な @PostConstruct
アノテーションと @PreDestroy アノテーションもサポートしています。XML ベースの方法を使用して Bean を定義する場合には、Bean 要素を使用してライフサイクル・コールバック・メソッドを定義します。以下のコードは XML ベースの構成で Bean 要素を使用してコールバックを定義する場合の一般的な方法を示しています。
リスト 7. ライフサイクル・コールバックに XML ベースの方法を使用する
<bean id="course" class="demo.Course" init-method="setup" destroy-method="cleanup" > <property name="module" ref="module"/> </bean> |
以下に示すのは Java ベースの構成でライフサイクル・メソッドを使用する場合のコードです。
リスト 8. AppContext 構成クラスを使用して Bean のライフサイクル・メソッドを実装する
@Configuration
public class AppContext {
@Bean(initMethod = "setup", destroyMethod = "cleanup")
public Course course() {
Course course = new Course();
course.setModule(module());
return course;
}
@Bean(initMethod = "setup", destroyMethod = "cleanup")
public Module module() {
Module module = new Module();
module.setAssignment(assignment());
return module;
}
...
}
public class Course {
private Module module;
private String name;
public Course() {
}
public void setup() {
this.name = "M100 Pythagoras Theorems"
}
public void setModule(Module module) {
this.module = module;
}
public void cleanup() {
module = null;
}
}
|
上記のコードでも、AppContext 構成クラスを使用しています。今度は @Bean アノテーションに initMethod と destroyMethod という 2 つの属性が追加されています。この 2
つの属性はライフサイクル・メソッドのセットアップとクリーンアップを定義しています。これらのメソッドは登録された Bean の中で実装された後、Bean が初期化される際と
Bean が破棄される前にコンテナーによって呼び出されます。ここで例として取り上げた Course Bean
はライフサイクル・メソッドの実装を提供しています。実装されるメソッドは setup と cleanup です。同様に、これらのメソッドを Module Bean と
Assignment Bean 内でも実装することができます。
Bean のスコープは @Scope アノテーションを使って定義することができます。XML ベースの方法では Bean 要素の中で scope 要素を指定しました。
リスト 9. XML ベースの方法で Bean のスコープを定義する
<bean id="course" class="demo.Course" scope="prototype" > <property name="module" ref="module"/> </bean> |
以下に示すのは Java ベースの構成を使用して Bean のスコープを定義する場合のコードです。
リスト 10. AppContext 構成クラスを使用して Bean のスコープを定義する
@Configuration
public class AppContext {
@Bean(initMethod = "setup", destroyMethod = "cleanup")
@Scope("prototype")
public Course course() {
Course course = new Course();
course.setModule(module());
return course;
}
...
}
|
上記のコードを見るとわかるように、Java 構成クラスの中で Bean のスコープを定義する方法は非常に簡単です。上記の AppContext 構成クラスは @Scope アノテーションを使用して Course Bean の prototype スコープを定義しています。デフォルトのスコープは singleton です。
Java ベースの構成を使用してできることは数多くありますが、この記事では基本的なことに触れたにすぎません。Java ベースの構成を使用することで非常に大きなメリットがあるわけではなく、Spring で XML ベースの構成の代わりに使用できるにすぎません。フレームワークに XML を使用することを好まない人には、Java ベースの構成方法は適しています。当然ですが、欠点としては、Java クラスの構成を少しでも変更した場合にはアプリケーションを再度コンパイルする必要があることです。
学ぶために
- 「Apache
CXF と Aegis を使用した Web サービスの開発: CXF と Aegis のデータ・バインディングを使用した Web サービスの開発方法を学ぶ」を読んでください。
- 「Spring、Apache CXF
を使用した POJO Web サービスの設計と実装: 第 1 回 CXF と Spring を使った Web サービス作成の概要」を読んでください。
- 「Spring、Apache
CXF を使用した POJO Web サービスの設計と実装: 第 2 回 RESTful な Web サービスを作成する」を読んでください。
- さまざまな IBM 製品や IT 業界のトピックに焦点を絞った developerWorks
の Technical events and webcasts で最新情報を入手してください。
- 無料の developerWorks
Live! ブリーフィングに出席し、IBM の製品やツール、また IT 業界のトレンドに関する最新情報を入手してください。
- Twitter で developerWorks
をフォローしてください。
- developerWorks On demand
demos をご覧ください。初心者のための製品インストール方法やセットアップのデモから、上級開発者のための高度な機能に至るまで、多様な話題が解説されています。
製品や技術を入手するために
- 皆さんの目的に最適な方法で IBM
製品を評価してください。製品の試用版をダウンロードする方法、オンラインで製品を試す方法、クラウド環境で製品を使う方法、あるいは
SOA Sandbox
で数時間を費やし、サービス指向アーキテクチャーの効率的な実装方法を学ぶ方法などがあります。
議論するために
- My developerWorks
コミュニティーに加わってください。開発者向けのブログ、フォーラム、グループ、ウィキなど利用しながら、他の developerWorks ユーザーとやり取りしてください。

Rajeev Hathi は J2EE プラットフォームに関するソフトウェア・コンサルタントです。彼はアーキテクチャーの設計、J2EE ベースのアプリケーションの設計や開発に専門的な関心を持っており、Java 技術と J2EE 技術 (コア Java、Web、EJB、アーキテクト) で SUN 認定を取得しています。また、IBM の developerWorks ポータルに何本かの技術記事を寄稿しているとともに、『Apache CXF Web Service Development』の共著者でもあります。彼の趣味は音楽鑑賞とスポーツ観戦です。彼の公式な Web サイトは技術ブログのサイト、http://www.rajeevhathi.comです。