■Spring Boot の小径 第4歩 Spring Boot 匍匐前進 |
4-1)コンポーネントスキャン |
■SpringMVC の小径では、個人的な好みでクラスの性質に合わせてパッケージ階層を分けました。 cntl/blogic/model........ みたいな感じですね そして、Spring設定ファイル(applicationContext.xml)で、コンポーネントスキャンの対象パッケージを定義しました。 <context:component-scan base-package="jp.dip.arimodoki.cntl"/> <context:component-scan base-package="jp.dip.arimodoki.blogic"/> <context:component-scan base-package="jp.dip.arimodoki.model"/> のような感じです。 Spring Boot ではそもそも、Spring設定ファイル自体存在しないため クラスのパッケージ階層を分けて、必要に応じて DI したい場合どうすればいいでしょう? 答えは、異なるパッケージ階層を使用する(DIする)クラスで、@ComponentScanアノテーションを宣言して 使用するパッケージを指定してあげれば利用可能となります。 下に、コントローラから、パッケージ階層を横断したクラスをDIするサンプルを作ってみました。 |
まずは、コントローラ src/main/java/jp/dip/arimodoki/cntl/HelloCntl.java このサンプルでは、コントローラでバインドされたFormBean(FormHello.java)を、 ビジネスロジック(BlHello.java)に継承し、ここでViewに表示するメッセージをセットします。 コントローラは、FormBeanをView(hellcntl.html)に返却しこのメッセージをブラウザに表示します。 ここでDIされるクラスのパッケージ階層は、 jp.dip.arimodoki.blogicと、 jp.dip.arimodoki.model のパッケージ階層を使用するため、 コントローラのクラス宣言部に、 @ComponentScan("jp.dip.arimodoki.blogic, jp.dip.arimodoki.model") で、パッケージのコンポーネントスキャン宣言を行っています。 スキャンするパッケージ階層が複数の場合は、カンマ(,)で区切って複数指定が可能です。 また、jp.dip.arimodoki.* のようにワイルドカードも使えます。 |
続いて、フォームBean src/main/java/jp/dip/arimodoki/model/FormHello.java Viewに表示する discriptionを、保持する単純なBeanです。 インターフェース FormHelloIf.java は Eclipse のリファクタリング(インターフェースの抽出)で自動生成します。 |
続いて、ビジネスロジック src/main/java/jp/dip/arimodoki/blogic/BlHello.java コントローラからFormBeanを受け取り FormHello Beanの discriptionに値をセットします。 このビジネスロジックも、FormBeanのパッケージ階層jp.dip.arimodoki.modelを使用するので クラス宣言部に@ComponentScan 宣言を行っています。 インターフェース BlHelloIf.java は Eclipse のリファクタリング(インターフェースの抽出)で自動生成します。 |
最後が、View src/main/resources/templates/hellocntl.html 基本的には、前に出てきた hello.html とほとんど変わりません。 一点だけ。表示する discription をFormHelloから取り出しているところだけが異なります。 |
それでは、このアプリケーションを実行してブラウザで確認してみましょう。 ブラウザのURLに、「http://localhost:8080/hellocntl」 を入力してみます。 |
いかがでしょうか? BlHello.javaでセットされた文字列が、期待通りブラウザに表示されました。 Spring設定ファイルで定義していたコンポーネントスキャン宣言が、 それを使用するクラスの先頭で直接指定できるので、直感的にわかりやすくなっていると思います。 まぁ、ほんのちょっとだけコーディング量は増えますけど。。。 |
|
※)どんでん返しのお話 2017/Apr/05 追記 ここまで話を盛り上げておいて、ここで今更いうのもなんですが、 クラスの数が増えると、一々クラスに@ComponentScanアノテーション付けるのがちょっと面倒ですよね? なんかいい方法ないでしょうか? 実はあります。一発逆転のテクニックをご紹介しましょう。 Gradleプロジェクト / Mavenプロジェクト どちらも一緒ですが Spring Boot プロジェクトが作成された時に自動生成されるメインクラス、 ProjectNameApplication.javaのクラスに、アノテーションを一行追加します。 このプロジェクトの例ですと、src/main/java/jp/dip/arimodoki/BootLaboApplication.java(抜粋) @SpringBootApplication @ComponentScan(basePackages = "jp.dip.arimodoki") public class BootLaboApplication { : : クラスのアノテーションで、上の赤字の行を一行追加します。 これだけで、ここでコンポーネントスキャン宣言されたパッケージ配下のクラスは全てComponentScan対象となり、 一々、個々のクラスに@ComponentScanアノテーションを宣言しなくてもよくなり、@ComponentScan宣言の手間が省けます。 対象パッケージが複数ある場合は、basePackagesにカンマ(,)区切りでパッケージ名を記述します。 このテクニックは、後述する Singleton一括排除の際にもまた出てきますので覚えておいてください。 |
3-1)Hello Spring Boot !! | 4-1)コンポーネントスキャン | 4-2)入力チェック |