Java ベースの構成を使用して Spring Bean を管理する
Java ベースの構成を使用して Spring Bean を管理する方法を学ぶ
概要
よく知られているように、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 ベースの構成を使用する方法について説明します。
Webアプリケーションを構成する方法
通常、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 のスコープ
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 サービスを作成する」を読んでください。
- Twitter で developerWorks をフォローしてください。
- 皆さんの目的に最適な方法で IBM 製品を評価してください。製品の試用版をダウンロードする方法、オンラインで製品を試す方法、クラウド環境で製品を使う方法、あるいは SOA Sandbox で数時間を費やし、サービス指向アーキテクチャーの効率的な実装方法を学ぶ方法などがあります。