@Autowiredは何がうれしいのか？

spring boot で、@Autowired アノテーションは何がうれしいのか？
都度、new する書き方だと何が不便なのか？がよくわからなかったため、調べたことをメモします。
DIコンテナがどうこう、という難しいことは一旦触れないで、直感的にわかりやすい部分だけ説明します。

## @Autowiredを使わない場合と、使う場合を比較

例えば、下記のような依存関係にある 3つのクラス Application, BusinessService, DatabaseService を比較します。ここでいう「依存」とは、クラスの引数に別のクラスのインスタンスをとっている、という意味です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1605263/30a70ee5-a942-13c5-8c23-0a6280d3215b.png)


```java:@Autowiredを使わない場合
public class DatabaseService {
    public void saveData(String data) {
        // データを保存するロジック
    }
}

public class BusinessService {
    private DatabaseService databaseService;

    public BusinessService(DatabaseService databaseService) {
        this.databaseService = databaseService;
    }

    public void processData(String data) {
        // データ処理のロジック
        databaseService.saveData(data);
    }
}

public class Application {
    private BusinessService businessService;

    public Application() {
        // 依存性の手動セットアップ
        DatabaseService databaseService = new DatabaseService();
        businessService = new BusinessService(databaseService);
    }

    public void run() {
        String data = "Some data";
        businessService.processData(data);
    }
}

```


```java:@Autowiredを使った場合
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class DatabaseService {
    public void saveData(String data) {
        // データを保存するロジック
    }
}

@Component
public class BusinessService {
    private DatabaseService databaseService;

    @Autowired
    public BusinessService(DatabaseService databaseService) {
        this.databaseService = databaseService;
    }

    public void processData(String data) {
        // データ処理のロジック
        databaseService.saveData(data);
    }
}

@Component
public class Application {
    private BusinessService businessService;

    @Autowired
    public Application(BusinessService businessService) {
        this.businessService = businessService;
    }

    public void run() {
        String data = "Some data";
        businessService.processData(data);
    }
}

```
この時点ですでに、@autowiredを使う方が**コードが少なくすっきり**していますが、autowiredのメリットはもう一つあります。

ここで、**BusinessServiceクラスの引数(= 依存先)インスタンスが、
databaseService から anotherDatabaseService へ変更**になったとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1605263/8bb688df-347e-ae40-4ed7-33bdaa503c0a.png)


「@Autowiredを使わない場合」のコードでは、anotherDatabaseServiceのクラスを定義するのに加えて、**Applicationクラスの定義も書き換えねばなりません**(下記)。

```java:「@Autowiredを使わない場合」は、Applicationクラスの定義も書き換えねばならない！
public class Application {
    private BusinessService businessService;

    public Application() {
        // DatabaseService を　AnotherDatabaseService　に書き換え
        AnotherDatabaseService anotherDatabaseService = new AnotherDatabaseService();
        businessService = new BusinessService(anotherDatabaseService);
    }

    public void run() {
        String data = "Some data";
        businessService.processData(data);
    }
}
```
しかし、「@Autowiredを使った場合」のコードでは、Applicationクラスの定義中に DatabaseService のインスタンスは表れないため、**DatabaseServiceとBusinessService間の依存関係が変化しても、わざわざApplicationクラスの定義を書き換えなくてよく**なります。

```java:(再掲、一部抜粋)@Autowiredを使った場合
//Applicationクラスの定義は、何も書き換えないでOK
public class Application {
    private BusinessService businessService;

    @Autowired
    public Application(BusinessService businessService) {
        this.businessService = businessService;
    }

    public void run() {
        String data = "Some data";
        businessService.processData(data);
    }
}
```

**DatabaseService に依存しているクラスが増えれば増えるほど、このメンテナンス性の良さが効いてくる**と考えられます。
最初は DatabaseService をスタブで開発したい(例：StabDatabaseService)時なども、最終的にStabDatabaseService を　DatabaseService　に切り替えなければなりませんが、@Autowiredを使えば、その時のコードの書き換え箇所が少なくなり、ラクになる、ということだと理解しています。