Java
spring
新人教育
spring-mvc
新人プログラマ応援

Spring での責務についてまず見てほしい一枚の絵

2018-05-30 追記

この記事は最終更新日から1年以上が経過しています。

というメッセージが長らく出ていたにも関わらず、今でもそこそこ読んでもらえているようなので、新たに 改訂版を書きました。


新年度を迎え、新たな職場、新たな環境で、はじめて Spring に触れている方も多いかと思います。
とくに、これまでは少人数開発しか経験してこなかったような新人さんがたにおいては、エンプラ開発では非常に多く採用されている Spring を、今まさに学んでいるという方、多いのではないでしょうか。
今回は Spring を学ぶにあたり、まずおさえておきたい基本的な考え方をまとめてみます。

全体俯瞰

Spring MVC には、それぞれ一定の責務を持ったコンポーネントが定義されており、その多くは特定のアノテーションに対応付けられています。
はじめに、それぞれの役割と相互関係を理解しておくことで、Spring MVC を扱う際の誤解や、誤った設計を防ぎ、Spring による開発プロジェクトの助けとなることでしょう。
全体を俯瞰すると、各コンポーネント間には、以下のような相互関係があるといえるでしょう。

spring-mvc3.png

各コンポーネントの責務

これらコンポーネントには、どのようなアノテーションが対応し、どのような責務を与えられているのか。
代表的なものを以下にまとめます。

コンポーネント 対応アノテーション 責務
Model データモデルレイヤを扱う。
POJO であることが望ましい。
View ビューレイヤを扱う。
Spring では、フロントにレスポンスされるものは、すべてビューとして定義される。HTML 書式のものだけでなく、JSON、XML、CSV、PDF、他も、等しくビュー表現のひとつとして扱われる。
Controller @Controller コントローラレイヤを扱う。
コントローラレイヤでは、フロントからのリクエスト、およびフロントへのレスポンスのハンドリングのみを行う。共通的な例外レスポンスや、レスポンスフォーマットの変換処理については、後述する @ContorollerAdvice を併せて利用する。
Service @Service サービスレイヤを扱う。
サービスレイヤでは主に、業務プロセスを表現する。
レスポンス、リクエストに依存したような処理や、永続化処理はこのレイヤではおこなってはならない。これら、他責務の処理記述が混在しはじめると、途端にテストの難易度が上がる。
Repository @Repository リポジトリレイヤを扱う。
リポジトリレイヤでは主に、永続化を表現する。
このレイヤでは実装に際し、抽象化したインターフェースを定義することを強く推奨する。抽象化しておくことで、例えばデータソースが、RDB から、KVS に変更された場合など、他責務レイヤへの影響が最小化され、変更をリポジトリレイヤのみに閉じることができる。
Template テンプレートレイヤを扱う。
テンプレートレイヤでは、それぞれのデータソースと、その永続化方法に応じた、共通的な永続化処理を表現する。(テンプレート = データソースタイプ x 永続化方法)
例えば、RDB をデータソースに取った、JDBC による永続化方法を表現するテンプレートには JdbcTemplate が存在したり、同じく、RDB をデータソースに取った、MyBatis による永続化方法を表現するテンプレートには SqlSessionTemplate が存在する。一方 MongoDB をデータソースに取った場合は、MongoTemplate が存在するなど、様々なデータソース、永続化方法に対応したテンプレートが用意されている。
Configuration @Configuration コンフィグレーションレイヤを扱う。
構成管理や設定などを表現する。
Advice @Aspect @ControllerAdvice AOP レイヤを扱う。
AOP では、メソッドの前や後、または前後に共通的な処理を後付けすることができ、同じような処理を何度も記述するのを抑制したり、本来の責務とは直接関係のない処理を、各責務から分離したりするのに役立つ。
たとえばパフォーマンスログの出力や、トランザクション境界の定義などを AOP に分離することができる。
また、@Aspect は、それ単体では DI コンテナに登録されないため、@Component@Bean と組み合わせて使用する。
なお、ビューレイヤ、コントローラレイヤ間における処理の多くは、@Aspect で、割り込みを行うことができないため、この箇所専用のアノテーションである @ControllerAdvice を利用する。
@Component その他、どのレイヤからも利用することが想定されるような、ユーティリティコンポーネントなどを表現するのに使用する。
なお、ユーティリティについては、DI の管理から外れてしまう static メソッドばかりを集めたようなユーティリティクラスは作成せず、@Component の付与されたユーティリティコンポーネントとして作成するように心がける。

おおむね以上のような感じでしょうか。
Spring Boot の登場により、非常に扱いやすくなったとはいえ、やはり巨大なフレームワークである Spring。
最初に基本をしっかりと押さえて、良き設計を心がけたい。