Spring BootでのDI

SpringやJavaEE等のフレームワークを使用すると、 **依存性注入（DI）** を行うのが非常に簡単になります。
「[Javaで簡単な自作DIを作成](https://qiita.com/yasushi-jp/items/43a61d38a4f4c9201dcc "Javaで簡単な自作DIを作成")」で自作アノテーションを使って **依存性注入（DI）** を行う方法を実施してみましたが、ここでは **Spring Boot** で **依存性注入（DI）** を行うサンプルプログラムを紹介します。

# 1. 環境

+ java：openjdk version "21.0.5"
```
C:\pleiades\2024-12\java\21\bin>java -version
openjdk version "21.0.5" 2024-10-15 LTS
OpenJDK Runtime Environment Temurin-21.0.5+11 (build 21.0.5+11-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.5+11 (build 21.0.5+11-LTS, mixed mode, sharing)

C:\pleiades\2024-12\java\21\bin>
```

# 2. 作成するファイル
作成するファイルは以下となります。
|No　|ファイル名|説明|
|:---|:---|:---|
|1|MyService.java|DI対象のクラス|
|2|DiSampleApplication.java|動作確認(Spring Bootのmain関数)|

# 3. Spring BootでのDIのサンプル作成
### 3.1. DI対象のクラス（MyService）を作成

```java:MyService.java
package com.example.ditest;

import org.springframework.stereotype.Service;

@Service
public class MyService {

	public void execute() {
        System.out.println("Service is doing executing...");
    }
}
```

### 3.2. 動作確認のためのMainクラス（DiSampleApplication）を作成

```java:DiSampleApplication.java（メソッドインジェクション）
package com.example.ditest;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class DiSampleApplication {

	public static void main(String[] args) {
		SpringApplication.run(DiSampleApplication.class, args);
	}

	@Bean
	CommandLineRunner run(MyService myService) {
		return args -> {
			myService.execute();
		};
	}

}
```
`@SpringBootApplication`は、Spring Bootアプリケーションを起動するためのアノテーションです。細かくいうと以下の3つのアノテーションをまとめたものとなります。
+ `@Configuration`: 設定クラスであることを示す
+ `@EnableAutoConfiguration`: Spring Boot が提供する自動設定を有効にする
+ `@ComponentScan`: 指定したパッケージ内のSpringコンポーネント（`@Component`、`@Service`、`@Repository`、`@Controller`など）を自動的にスキャンし、Springコンテナに登録する

なお、このサンプルプログラムだと`@SpringBootApplication`の代わりに以下でも問題ありません。
```java
@Configuration
@ComponentScan
```
または
```java
@Configuration
@ComponentScan(basePackages = {"com.example.ditest"})
```

&nbsp;

`SpringApplication.run()`メソッドを呼び出すことによって、Spring Bootアプリケーションが起動し、アプリケーションコンテキストが初期化されます。

&nbsp;

`CommandLineRunner`は、Spring Bootのインターフェースで、アプリケーションが起動した直後に実行されるコードを定義するために使用します。
`run(MyService myService)`メソッドは`CommandLineRunner`を返します。引数に`MyService`を受け取ることで、Springによって自動的に`MyService`が **インジェクション** されます。

&nbsp;

「[Javaで簡単な自作DIを作成](https://qiita.com/yasushi-jp/items/43a61d38a4f4c9201dcc "Javaで簡単な自作DIを作成")」と比べると、 **Spring Boot** を使用すると **依存性注入（DI）** の手間がものすごく簡略化されるていることがわかります。面倒なところは裏で **Spring Boot** が自動で実施してくれるため、より簡単に **依存性注入（DI）** を使うことができます。

&nbsp;
 　

なお、以前は以下のように`@Autowired`を使用して、フィールドインジェクションを使用することもありましたが、現在は推奨されていないようです。

```java:DiSampleApplication.java（フィールドインジェクション - 非推奨）
package com.example.ditest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class DiSampleApplication {

	@Autowired
	private MyService myService;

    public static void main(String[] args) {
		SpringApplication.run(DiSampleApplication.class, args);
	}

	@Bean
	CommandLineRunner run() {
		return args -> {
			myService.execute();
		};
	}

}
```

なお、以下のように書くこともできます。

```java:DiSampleApplication.java（コンストラクタインジェクション）
package com.example.ditest;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class DiSampleApplication {
	
	private final MyService myService;
	
	public DiSampleApplication(MyService myService) {
		this.myService = myService;
	}
	
	public static void main(String[] args) {
		SpringApplication.run(DiSampleApplication.class, args);
	}

	@Bean
	CommandLineRunner run() {
		return args -> {
			myService.execute();
		};
	}

}
```
# 4. 実行結果
`DiSampleApplication`を実行すると、以下の通り`MyService`クラスの`execute`メソッドが実行されていることがわかります。

```console:実行結果

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.4.2)

2025-03-16T15:38:11.625+09:00  INFO 14100 --- [springboot] [  restartedMain] com.example.ditest.DiSampleApplication   : Starting DiSampleApplication using Java 21.0.5 with PID 14100 (C:\pleiades\2024-12\workspace\springboot\bin\main started by local_yasushi in C:\pleiades\2024-12\workspace\springboot)
2025-03-16T15:38:11.627+09:00  INFO 14100 --- [springboot] [  restartedMain] com.example.ditest.DiSampleApplication   : No active profile set, falling back to 1 default profile: "default"
2025-03-16T15:38:11.701+09:00  INFO 14100 --- [springboot] [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2025-03-16T15:38:12.572+09:00  INFO 14100 --- [springboot] [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2025-03-16T15:38:12.616+09:00  INFO 14100 --- [springboot] [  restartedMain] com.example.ditest.DiSampleApplication   : Started DiSampleApplication in 1.558 seconds (process running for 2.266)
Service is doing executing...
```

---

以上