SpringSourceはSpring 3.1のリリース候補版を発表した。 Spring 3.1.0.RC1の特徴は下記の通り。
- 環境の抽象化とBeanプロファイル
- 包括的な@Configuration
- キャッシュの抽象化
- c: 名前空間
- MVCサポートの強化
- JPAサポートの強化
- Hibernate 4.0とQuartz 2.0のサポート
- Servlet 3.0のサポート
- Java 7とJDBC 4.1とForkJoinPool
これでSpring 3.1の特徴は一通り揃ったことになる。Spring 3.1 GAのリリースは2011年11月の後半に予定されている。この記事ではSpring 3.1の新しい特徴を概括する。
環境の抽象化とBeanプロファイル
Spring 3.1は環境毎のプロファイルという概念を導入する。これは開発環境、品質保証環境、運用環境毎にセットアップするBeanを変えるという使い方を想定している。開発環境ではスタンドアロンのデータソースを使い、運用環境ではJNDI経由でデータソースを探すように設定するというのが典型的な使用例だ。また、プロファイルの設定を簡単に変更できるようにするためにBeanプロファイルとして利用することもできる。これはXMLのBean要素にプロファイル属性を追加したり、コード上に@Profileアノテーションを記述することで実現できる。ただし、SpringのBeanは複数のプロファイルに割り当てることができるのに注意する必要がある。
<beans profile="dev"> ... </beans>
@Profile("dev") public class Bean { ... }
これらのプロファイルはspring.profiles.activeプロパティで有効化できる。このプロパティは環境変数でも設定できるし、JVMのシステムプロパティや、web.xmlやJNDIのServletの<init-param>でも設定できる。また、コードでEnvironment.setActiveProfiles(String ...)を使って有効化することもできる。プロファイルを動作させるために、ファイルの末尾に限定して、Spring XMLでネストしたBean要素が記述できるようになる。Beanの定義の仕方はなるべく各環境の設定を考慮すべきだ。そうすれば、各環境を適切にテストできるからだ。
また、異なる複数のプロパティ情報の中からEnvironment.containsProperty()メソッドを使ってプロパティを探すこともできる。XMLのBean定義に${placeholder}変数を使ってプロパティを解決することも出来る。
包括的な@Configuration
これまでJavaベースのアプリケーションの構成方法は進化してきた。Spring 3.1ではXMLの名前空間と同じ機能を提供するアノテーションが提供される。@Enableアノテーションと@ConfigurationクラスがXMLの <context:component-scan/>, <tx:annotation-driven/>や<mvc:annotation-driven>のような名前空間要素と同等の機能を提供するため開発された。新しいアノテーションは下記の通り。
org.springframework.context.annotation.Configuration org.springframework.context.annotation.ComponentScan org.springframework.context.annotation.EnableLoadTimeWeaving org.springframework.context.annotation.EnableAspectJAutoProxy org.springframework.scheduling.annotation.EnableScheduling org.springframework.scheduling.annotation.EnableAsync org.springframework.transaction.annotation.EnableTransactionManagement org.springframework.web.servlet.config.annotation.EnableWebMvc
TestContextフレームワークは@Configurationクラスと環境プロファイルをファーストクラスでサポートするために徹底的に見直された。@ContextConfigurationアノテーションはSpring TestContextを構成するために@Configurationクラスをサポートする。また、@ActiveProfilesアノテーションも追加された。これは、宣言的なプロファイルの構成をサポートするためだ。
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(loader = AnnotationConfigContextLoader.class) @ActiveProfiles("dev") public class Test { @Configuration static class ContextConfiguration { ... } ... }
キャッシュの抽象化
Spring 3.1では、新しい@Cacheableアノテーションか、XMLで<cache:advice>要素を使うことで透過的なキャッシュの追加が可能になる。
<beans ... xmlns:cache="http://www.springframework.org/schema/cache" http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> <cache:annotation-driven /> ... </beans> @Cacheable("cache") public String get(String s) { ...
@Cacheableアノテーションを使うことでアノテーションが付加されたメソッドの実行を定期的にチェックし、Javaのメソッドの結果をキャッシュできる。メソッドがある特定の引数で既に呼ばれていたら、キャッシュの結果が返されて、実際にはメソッドは実行されない。もちろん、このキャッシュは同じ引数なら必ず同じ結果を返すメソッドでしか動作しない。すぐに使えるキャッシュの実装はJDKの java.util.concurrent.ConcurrentMapとEhcacheだ。また、@CacheEvictアノテーションもある。このアノテーションを使うとメソッドはキャッシュを追い出せる。キャッシュ内の使っていないデータ、古いデータを削除できるのだ。他にもカスタムのキャッシュキーの生成や条件付きキャッシュのような新しい機能がある。
c: 名前空間
p:名前空間と同じように、Spring 3.1には新しいc:名前空間が追加された。これを使えばネストした<constructor-arg>要素ではなく属性でコンストラクタの引数を構成できる。
<-- constructor-arg --> <bean ...> <constructor-arg value="val" /> </bean> <-- c: namespace --> <bean ... c:arg="val">
MVCサポートの強化
Spring 3.1はMVCを改訂してフラッシュ属性、新しい@RequestPartアノテーション、URIテンプレート、パス変数、コンテントタイプに体するRESTサポートの強化が行われた。
フラッシュ属性はあるリクエストで属性を保持し別のリクエストでその保持した属性を利用するための方法を提供する。ほとんどの場合Post/Redirect/Getパターンのようなリダイレクトを挟むリクエストで利用させる。保存されたフラッシュ属性はリダイレクト後のリクエストで利用でき、その後、すぐに消される。この手法では並列処理が問題になる可能性があるので、フラッシュ属性はリダイレクト対象のURLのパスとクエリのパラメータにフラッシュ属性を関連づけることで問題が最小になるようにしている。@RequestMappingメソッドはRedirectAttributes型の引数を取り、フラッシュ属性を追加できる。
@RequestMapping(value = "/", method = RequestMethod.POST) public String foo(RedirectAttributes redirectAttributes) { ... }
新しい@RequestPartアノテーションはメソッドの引数の"multipart/form-data"の部分と関連して使う。このアノテーションを使うとマルチパートのコンテントタイプを考慮して、特定のマルチパートのコンテンツをHttpMessageConverterへ渡すことができる。
@RequestMapping(value="/", method = RequestMethod.POST) public String foo(@RequestPart("file") MultipartFile file) { ... }
Spring 3.1にはアノテーションが付加されたコントローラでリクエストを処理するための新しいクラスが用意されている。RequestMappingHandlerMapping、RequestMappingHandlerAdapter、ExceptionHandlerExceptionResolverの3つだ。この3つのクラスはそれぞれDefaultAnnotationHandlerMapping、AnnotationMethodHandlerAdapter、AnnotationMethodHandlerExceptionResolverの3つの代替物だ。これらの新しいクラスはアノテーションコントローラがカスタマイズ可能で拡張しやすいかたちでクラスをサポートできるようにするために開発された。将来はこれらのクラスを使うことが推奨されている。
受け付けるメディアタイプと出力するメディアタイプのリストを定義することでリクエストのマッピングを制限できる。受け付けるメディアタイプはContent-Typeヘッダとリストアップしたメディアタイプが合うだけ、適合するリクエストと判断される。出力するリクエストの場合はリクエストのAcceptタイプで同じように判断する。
@RequestMapping(value = "/", method = RequestMethod.POST, consumes="application/json") public void foo() { ... } @RequestMapping(value = "/", method = RequestMethod.POST, produces="application/json") public void bar() { ... }
また、URIテンプレート変数が強化されている。リクエストを@ModelAttributeの引数にバインドしているとき、リクエストのパラーメタに加えてURIテンプレート変数も使えるようになる。@PathVariableメソッドの引数は描画前にこのモデルにマージされる。リダイレクトの文字列にはURI変数のプレースフォルダを含むことができ、@ModelAttributeメソッドの引数は登録されたConverterかPropertyEditorがある限りURIテンプレート変数からインスタンス化される。
JPAサポートの強化
Spring 3.1では、JPA EntityManagerFactoryをpersistence.xmlや他のメタデータファイルなしで利用できる。LocalContainerEntityManagerFactoryBeanのpackagesToScanプロパティを使うことで、you can specify the base packages to scan for @Entityクラスをスキャンするためのベースパッケージを定義できる。AnnotationSessionFactoryBeanクラスの同じ名前のプロパティがHibernateのセットアップを行う場合や、Springのcomponent-scanが通常のSpring Beanをセットアップする場合と同じだ。
Hibernate 4.0とQuartz 2.xのサポート
Spring 3.1はHibernate 4.0とQuartz 2.xをサポートする一方、古いバージョンとの互換性も維持する。Hibernate 4のサポートについての詳細はorg.springframework.orm.hibernate4パッケージに含まれるクラスのJavadocを見るといいだろう。このパッケージが最小の内容しか含まず、SessionFactoryの作成をHibernateのビルダーAPIに依存しているのは意図的だ。Quartz 2.xはクラスをインターフェイスに変換するので、古いバージョンのSpringには互換性がなくjava.lang.InstantiationErrorが発生してしまう。Spring 3.1はこの問題に対処しつつ、Quartz 1.xとの互換性も維持している。
Servlet 3.0のサポート
Spring 3.1ではServlet 3.0のServletContainerInitializerとMultipartResolverが利用できる。Springの新しい WebApplicationInitializerはServletContainerInitializerの上で動作し、プログラミングできるweb.xmlの代替物として動作する。下記のリンクはSpringSourceのグリーンハウスリポジトリのコミットページだ。
https://github.com/SpringSource/greenhouse/commit/213d2c742d472e602defcde801dd118e098d73c6
Java 7とJDBC 4.1とForkJoinPool
最初はSpring 3.2で計画されていたのだが、Java 7がSpring 3.1でサポートされる。JDBC 4.1の自動検知とForkJoinPoolの基本的なサポートも提供される。SpringのDataSourceとRowSetのアダプタもJDBC 4.1と互換性を持たせるために更新されている。また、ForkJoinPoolFactoryBeanが導入される。これは事前に構成されたForkJoinPoolの構築するFactoryBeanだ。
その他の特徴
Spring 3.1では標準的でないJavaBeansのセッターに対してもインジェクションができる。これは、セッターメソッドがそのオブジェクトの参照そのものを返す、メソッドチェーンを実現するのに便利だ。初期のSpringではプロパティメソッドにインジェクトする場合、そのメソッドは厳格にJavaBeansのプロパティのルールに従わなければならなかった。つまり、セッターメソッドはvoidでなければならなかった。
また、カンバセーション機能のサポートは3.1には含まれないことに注意したい。需要がなかったためサポートは見送られたが、Spring 3.2ではサポートされるかもしれない。この機能は"HttpSession++"と呼ばれている、従来よりも柔軟なライフサイクルとストレージを持つセッションの仕組みでブラウザのタブと連携して使える。
ここで紹介した新しい機能を試すに、SpringコミュニティダウンロードページからSpring 3.1 RC1のリリースをダウンロードできる。また、Mavenを使っているならhttp://maven.springframework.org/milestoneリポジトリからSpring 3.1 RC1を取得できる。
<repository> <id>org.springframework.maven.milestone</id> <name>Spring Maven Milestone Repository</name> <url>http://maven.springframework.org/milestone</url> </repository> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>3.1.0.RC1</version> </dependency>
さらに詳しい情報はSpring 3.1 RC1のリファレンス、Javadoc API、変更ログから確認できる。Springミュニティフォーラムで質問するのもいいだろう。