Spring DIは何をするの?
- インスタンス管理をする
- @Autowiredアノテーションをフィールドなどに付けると、DIコンテナからインスタンスを取得
- DIによってクラスをnewしたり、使い終わった変数にnullを入れる必要がなくなる
DI の2つの機能
-
インスタンスの生成
- DIコンテナの中で、インスタンスを生成=クラスをnew
- アプリケーションではこのインスタンスを取得して利用
- DIの中で、毎回newしたインスタンスをアプリケーションに渡すのか、それとも、一度newしたインスタンスをアプリケーションに渡すのかを管理
-
インスタンスのライフサイクル管理(インスタンスの破棄)
- サーブレット(バックエンド)のリクエストスコープ (サーブレット、JSP間を跨いでデータを共有したい場合に用いる保存領域) や、セッションスコープにインスタンスを簡単に登録できる
Javaにおける依存って何?
- 依存というのは、他のクラスを利用しているかどうか
- 他のクラスをローカル変数として持っている
- 他のクラスがメソッドの引数、戻り値になっている
- 以下の例では車がエンジンを使うため、車クラスはホンダのエンジンクラスに依存していることになる
//車クラス
public classCar{
//ホンダのエンジン
private HondaEngine hondaEngine;
//コンストラクタ
public class Car(HondaEngine hondaEngine){
//ホンダのエンジンをセット
this.hondaEngine = hondaEngine;
}
}
//車を作る(=new)するMainクラス
public class Main{
public static void main(String[]args){
//パーツの生成
HondaEngine hondaEngine = new HondaEngine();
//車の生成
Car car = new Car(hondaEngine);
}
}
依存度合い
-
密結合:依存度が高い状態
- 上の例では別の会社のエンジンに変更したい場合、CarクラスとMainクラスの両方を修正する必要=密結合
- 日産のエンジンクラスが完成してないとテストができない=変更に弱いアプリケーションになってしまっている。。
→インターフェースを使って結合度を下げる!
-
車の部品を自由に交換できるようインターフェース作成
- インターフェースを継承したクラスでは、これらのメソッドを必ず実装する必要
- メソッド内に起動と停止時の具体的な処理をSBの記述
Engineインターフェース
//Engineインターフェース
public interface Engine {
public void boot();//起動メソッド
public void stop();//停止メソッド
}
Engineインターフェース実装クラス
//Engineインターフェースを継承したHondaEngineクラス
public class HondaEngine implements Engine {
//コンストラクタ
public HondaEngine(){
super();
}
//起動メソッド
@Override
public void boot(){
System.out.println("ホンダエンジン起動");
}
//停止メソッド
@Override
public void stop(){
System.out.println("ホンダエンジン停止");
}
}
Carクラス
- フィールド(データ)をインターフェースに変更
- インターフェースの起動・停止メソッドを利用するメソッドを用意
public class Car{
//エンジン
private Engine engine;
//コンストラクタ
public Car(Engine engine){
this.engine=engine;
}
//エンジンをかける
public void engineStart(){
engine.boot();
}
//エンジンをとめる
public void engineStop(){
engine.stop();
}
}
Mainクラス
- インターフェース型の変数には、それを継承したサブクラスのインスタンス(HondaEngine)を入れることが可能
//Engine型の変数にHondaEngineインスタンスを入れている
public class Main{
public static void main(String[]args){
//エンジンの生成(HondaEngine)
Engine engine = new HondaEngine();
//車クラスの生成
Car car = new Car(engine);
//エンジンをかける
car.engineStart();
//エンジンをとめる
car.engineStop();
}
}
クラス図
- 車クラスはEngineインターフェースに依存、HondaEngineクラスには依存しない
- →エンジン種類を変更したい場合、新しい別のEngineクラスを用意して、Mainクラス修正のみ
- →車クラスは修正しなくていい、依存度合いが低い!=疎結合👍👍
- 車クラスのテストはエンジンインターフェースを継承したダミークラスを用意してテストできる
※クラス図の見方
- 四角の上からクラス名の区域、フィールドの区域、メソッドの区域
- フィールド:可視性 名前:型 = 初期値
- メソッド:可視性 名前(引数リスト):返り値
- 引数リスト:名前:型 をコンマで区切る
- 可視性記号
表記 | 意味 |
---|---|
+ | public:どこからでもアクセス可能 |
# | protected:クラス内および派生したクラスからアクセス可能 |
- | private:クラス内でのみアクセス可能 |
~ | package:パッケージ内でアクセス可能 |
- 点線矢印 : 依存関係 (車クラスはホンダのエンジンクラスに依存)
- 三角矢印の点線: 実装クラスからインターフェースを指す (ホンダエンジンクラスはエンジンインターフェースを継承)