【Java】Spring DI ①

#Spring DIは何をするの？
* インスタンス管理をする
    * @Autowiredアノテーションをフィールドなどに付けると、**DIコンテナからインスタンスを取得**
    * DIによってクラスをnewしたり、使い終わった変数にnullを入れる必要がなくなる

#DI の2つの機能
* **インスタンスの生成**
    * DIコンテナの中で、インスタンスを生成=クラスをnew
    * アプリケーションではこのインスタンスを取得して利用
    * DIの中で、毎回newしたインスタンスをアプリケーションに渡すのか、それとも、一度newしたインスタンスをアプリケーションに渡すのかを管理

* **インスタンスのライフサイクル管理（インスタンスの破棄）**
    * サーブレット（バックエンド）のリクエストスコープ (サーブレット、JSP間を跨いでデータを共有したい場合に用いる保存領域) や、セッションスコープにインスタンスを簡単に登録できる

#Javaにおける依存って何？
* 依存というのは、他のクラスを利用しているかどうか
    * **他のクラスをローカル変数として持っている**
    * **他のクラスがメソッドの引数、戻り値になっている**
* 以下の例では車がエンジンを使うため、車クラスはホンダのエンジンクラスに依存していることになる


```Java
//車クラス
public classCar{
    //ホンダのエンジン
    private HondaEngine hondaEngine;
    //コンストラクタ
    public class Car(HondaEngine hondaEngine){
    //ホンダのエンジンをセット
    this.hondaEngine = hondaEngine;
        
    }
}
```

```java
 //車を作る(=new)するMainクラス
public class Main{ 
    public static void main(String[]args){
    //パーツの生成
    HondaEngine hondaEngine = new HondaEngine();
    //車の生成
    Car car = new Car(hondaEngine);
    }
}
```

##依存度合い
* **密結合**：依存度が高い状態
    * 上の例では別の会社のエンジンに変更したい場合、CarクラスとMainクラスの両方を修正する必要=**密結合**
    * 日産のエンジンクラスが完成してないとテストができない=**変更に弱いアプリケーション**になってしまっている。。
* **→インターフェースを使って結合度を下げる！**

* 車の部品を自由に交換できるよう**インターフェース**作成
    * インターフェースを継承したクラスでは、これらのメソッドを必ず実装する必要
    * メソッド内に起動と停止時の具体的な処理をSBの記述 

###Engineインターフェース
```java
//Engineインターフェース
public interface Engine {
    public void boot();//起動メソッド
    public void stop();//停止メソッド
}
```
###Engineインターフェース実装クラス

```java
//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）を入れることが可能

```java
//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クラス修正のみ
* →車クラスは修正しなくていい、**依存度合いが低い！=疎結合👍👍**　
* 車クラスのテストはエンジンインターフェースを継承したダミークラスを用意してテストできる

![クラス図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282755/d1788008-b6fa-8c5d-4b49-cf517e2f296f.png)

#### ※クラス図の見方
* 四角の上からクラス名の区域、フィールドの区域、メソッドの区域
    * **フィールド**：可視性 名前:型 = 初期値
    * **メソッド**：可視性 名前(引数リスト):返り値
    * **引数リスト**：名前:型 をコンマで区切る
* **可視性記号**

| 表記 | 意味 |
|:-:|:-:|
| +  | public:どこからでもアクセス可能 |
| #  | protected:クラス内および派生したクラスからアクセス可能 |
| -  | private:クラス内でのみアクセス可能 |
| ~  | package:パッケージ内でアクセス可能  |
	
* **点線矢印** : 依存関係 (車クラスはホンダのエンジンクラスに依存)
* **三角矢印の点線**: 実装クラスからインターフェースを指す (ホンダエンジンクラスはエンジンインターフェースを継承)