
- 作者:原田 けいと,竹田 甘地,Robert Segawa
- 発売日: 2020/05/23
- メディア: Kindle版
@Component と @Autowired を使用して、 Spring Framework の中心とも言える DI ( Dependency injection : 依存性の注入 ) の基本について学習する。まずは最小限の簡単なサンプル。
@Component public class ClassA { @Autowired private ClassA classA; }
@Component は インスタンスを Spring 管理下におくため、クラスに付けるアノテーション。
@Autowired は Spring 管理下のオブジェクトの中から、適切なものを変数に自動でセットしてもらうため、インスタンス変数に付けるアノテーションである。
SpringMVC や Spring Boot では、慣習的に @Component の変わりに @Controller、@Service、@Repository を使用する。
慣習的にと言ったのは、これら3つのアノテーションは、すべて @Component を継承しており、ソースコードレベルでの差異はないからである。
ソースのリンクを貼っておく。
では早速 DI のサンプルを作っていこう。
フォルダ構成
フォルダ構成は以下のとおり。
[org.yyama.bean]パッケージ配下の2つのクラスを Spring のコンテナに管理させる。Main クラスは Spring の管理外にする。
ソース
まず、applicationContext.xml。org.yyama.bean 配下を Spring がスキャンして、管理下とする bean を探す設定にしている。「<context:component-scan ・・・」となっている一行がその設定。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="org.yyama.bean" /> </beans>
クラスA。
package org.yyama.bean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class ClassA { @Autowired private ClassB classB; public void proc() { classB.print(); } }
@ComponentでSpringコンテナに管理させるクラスとして宣言している。@Autowired を使用してクラスBのインスタンスを Spring で自動的にセットしてもらう。
クラスB。
package org.yyama.bean; import org.springframework.stereotype.Component; @Component public class ClassB { public void print() { System.out.println("ClassBのprint()メソッドです。"); } }
@Component で Springコンテナに管理させるクラスとして宣言している。
最後に Main クラス。
package org.yyama; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.yyama.bean.ClassA; public class Main { public static void main(String... args) { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); ClassA classA = ctx.getBean(ClassA.class); classA.proc(); ctx.close(); } }
コンテナから、ClassA のインスタンスを取り出して proc() メソッドを実行する。このとき ClassA のプロパティ classB には Spring が自動で ClassB のインスタンスをセットしてくれるはずだ。
実行結果
ClassBのprint()メソッドです。
期待通り、クラスBの print() メソッドが呼び出されて"ClassBのprint()メソッドです。"というメッセージが表示されている。
@Autowired アノテーションをプロパティに記述しておくと、Spring がコンテナの中からその「プロパティの型に合うクラス」のインスタンスを裏で new して返してくれるというわけだ。
ん?、同じ型が2つ以上あった場合、Spring はどのインスタンスを DI すればいいか迷ってしまうのではないか?
その場合の対処方法は以下の記事を参考にして欲しい。
何がうれしいのか
「ClassA の中で ClassB を普通に new すればいいじゃないか」という NEW おじさんの声が聞こえてきた。確かに小さいプログラムであれば Spring など使用しないで new したほうが早い。
ある程度のアプリケーションになると、以下のような状況が考えられる。
・ClassB がまだできていないので ClassA のテストができない。
・ClassB が DB アクセスを行うので、ClassA を単体テストしたいだけなのに DB 構築が必要。
・ClassB を改良した NewClassB が発明された。ClassA を修正することなく NewClassB を使用したい。
このような場合、設定ファイルをいじるだけで、自動的にプロパティ classB には Mock が設定されるなどプログラムの修正を行わずに、依存するクラスを変更できる。
まとめ
Springは当初 DI コンテナとして生まれてきた。その後、周辺のいろいろな機能が追加された。
その各機能でも DI の機能を利用することになるので、DI については、自分でサンプルを組んでしっかり習熟しておきたい。

- 作者:掌田 津耶乃
- 発売日: 2017/12/20
- メディア: 単行本