ぺんぎんらぼ

お笑いとマンガ好きなしょぼしょぼWeb系エンジニアの日記です。たまに絵を描きます。

お笑いとマンガ好きなしょぼしょぼWeb系エンジニアの日記です

Spring MVCの概要を理解する

今回アプリを作るにあたってSpringの仕組み自体もきちんと理解しようと思い、

Spring3入門 ――Javaフレームワーク・より良い設計とアーキテクチャを購入しました。この本は少し中級者向けな感じがして、自分が読めたのは1/3くらいです・・・。また、Strutsとの連携方法とか、今となっては古く感じられるテーマもあります。こういった点はあるのですが、個人的には構造とか考え方について、日本語で読めるSpring本の中では一番内容がしっかりしている本だと思います。

  1. Spring MVCの特徴
  2. Spring MVCでWebアプリケーションを作る特長
  3. Spring MVCが動く仕組み(プレゼンテーション層)
1. Spring MVCの特徴
  • Spring MVCMVC型のフレームワークであること
  • アノテーションの採用(たとえばControllerクラスを作成するためにControllerインターフェースをimplementsする必要がなくなりクラスに@Controllerアノテーションを宣言するだけでいい)
  • SpringのControllerは、RESTの実装方式(RESTではWeb上の情報の一つ一つをリソースとしてとらえ、それらの識別子としてURIを割り当ててユニークに特定できるようにすることSpringのControllerもURLとメソッドを直接結びつけている)
  • DIという技術を使っている
  • AOPという技術を使っている
2. Spring MVCのWebアプリケーションの特長

普通にWebアプリを作ると、次のような3つの問題がある。

A. オブジェクトのライフサイクルの問題
・・・コントローラを実現するServletは、View部分にアクセスするユーザ数が増えるたびにインスタンス化されることによるガーベージコレクト時のパフォーマンス低下やメモリへの圧迫を防ぐよう、マルチスレッドで動作させる。しかし、コントローラから呼ばれるサービスロジックのオブジェクトを毎回インスタンス化するように設計・実装させてしまえば、View部分にアクセスするユーザ数が増えたときにインスタンスが増大し、ガーベージコレクト時のパフォーマンス低下やメモリの圧迫が発生してしまう恐れがある。これを防ぐためには、サービスロジックのオブジェクトはSingletonにしなければならない・・・(37頁)

B. 部品化の問題
Webアプリケーションを構成するオブジェクト間の依存関係は、インタフェースを介して実装非依存にすることでオブジェクト間を疎結合に保つことができる。・・・しかし、Springのようなフレームワークを利用せずに、このようなインタフェース依存・実装非依存を実現するにはテクニックを要する。例えば、単にインタフェースを利用するだけでは、実装非依存にならない。そこで、通常はFactoryMethodなどを導入して、実装非依存を実現する。(37-38頁)

C. 技術隠蔽や不適切な技術隠蔽の問題 ・・・顧客クラスや受注クラスの中に、顧客や受注の処理とは言いがたいトランザクションの例外、ロギングのような処理が入ってくるのは、プログラムの可読性を著しく落としてしまう。また、例外処理がいくつも書かれているということは、ソースコード中の分岐が増えるということは、可読性はもちろん、Unitテストの容易性だって落としてしまうことになる。(39-40頁)

で、それぞれの問題は、以下のような感じ、DIコンテナ×AOPで解決できる。
A. オブジェクトのライフサイクルの問題  →DIコンテナで解決
B. 部品化の問題  →DIコンテナで解決
C. 技術隠蔽や不適切な技術隠蔽の問題  →AOPで解決

■DIコンテナとは * オブジェクト、オブジェクト同士の関連を生成をする * インタフェースベースのコンポーネントを容易に実装可能にする * あるオブジェクトのプロパティにそのオブジェクトにそのオブジェクトが利用(依存)するオブジェクトを設定(作成)すること。 * 普通のWebアプリだと、各オブジェクトが別のオブジェクトを直接newして利用するので、密結合になってしまうが、 SpringのDIコンテナが入ることで、各オブジェクトの依存関係が解消される(48頁)。

f:id:penguinlabo:20200107151554p:plain f:id:penguinlabo:20200107151609j:plain

インタフェースに関連しているではないか、と思うのだが、「DIを利用するときは、原則としてクラスはインタフェースのみに依存して、具象クラスには依存しないようにする必要がある」らしい。

  • DIコンテナの実体の核になるのはBeanFactory。BeanFactoryは、その実行時に渡されるBean定義ファイルに基づいてファイルを生成し、インスタンスのインジェクションを行う。
    インジェクションの意味はよく分からなかったorz

AOPとは
* オブジェクトの責務以外のロジック(ユーザ認証やロギング、トランザクション管理や例外処理)をソースコードに記述することなく、後から追加できる。

3. Springが動く仕組み

f:id:penguinlabo:20200107151711p:plain

① DispacherServletはブラウザからリクエストを受け取る
② DispacherServletは、リクエストされたURLをHandlerMappingオブジェクトに対してよびだし対象のControllerオブジェクトを取得し、URLに該当するメソッドを実行する
② Controllerオブジェクトはビジネスロジックを使用して処理を実行し、その結果を基にビューに渡すオブジェクトをModelオブジェクトに格納する。最後にControllerオブジェクトは処理の結果に応じてView名を返す
④ DispacherServletはControllerから返されたView名をViewResolverに渡し、Viewオブジェクトを取得する。
⑤ DispacherServletはViewオブジェクトに画面表示を依頼する
⑥ Viewオブジェクトは該当するビューを呼び出して画面表示を依頼
⑦ ビューはModelオブジェクトから画面表示に必要なオブジェクトを取得し、画面表示処理を実行する

DispacherServlet イメージはSpringを制御するクラス。すべてのHTTPリクエストを受け付けて、HandlerMappingオブジェクトから取得したControllerオブジェクトのメソッドを実行。その他のオブジェクトの流れを制御する。基本的には用意されているDispatcherServletクラスをそのまま使う。
HandlerMappingオブジェクト DispacherServletからの要請を受けて、URLから、呼び出すControllerオブジェクトを返却する。
Viewオブジェクト ViewインタフェースをImplemtensしたViewオブジェクト。Webコンテナ上で管理されているJSPといったリソースに対してforwardをしてくれる「InternalResourceView」などがある。

・・・上の流れには登場しないが、このほかにも各クラスの依存性を解消して疎結合に保つための色んなクラスがある。

以上、今回はここまで。