Spring Boot CommandLineRunnerを使った初期処理の実行

# 初期化処理の作成
Spring BootではDIコンテナに全てのBeanが登録された後、CommandLineRunnerインターフェイスを実装したBeanが実行される。これを利用し、起動時にDBへデータを登録するといった初期処理を実装できる。
やり方は簡単で、CommandLineRunnerインターフェイスを実装し、runメソッド内に実行したい処理を記述したクラスをDIコンテナへ登録すればよい。 ここでは例として@Componentを使用する。下記の例では開発環境(Profile = "dev")で起動した場合にリポジトリクラスを使用しDBへ初期データを保存する。

```kotlin
@Component
@Profile(value = ["dev"]) // 開発環境のプロファイルの場合は実行
class DevDataInitializer(@Autowired private val greetingRepository: GreetingRepository) : CommandLineRunner {

    private val logger = LoggerFactory.getLogger(javaClass)

    override fun run(vararg args: String?) {

        logger.info("${this.javaClass.simpleName} Run")
        greetingRepository.save(Greeting(value = "Dev!!!"))
    }
}
```

下記のクラスは例なので、処理に特に意味はない。
リポジトリクラス

```kotlin
import com.example.springsecuritydemo.domain.Greeting
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

@Repository
interface GreetingRepository: JpaRepository<Greeting, Long>
```

エンティティクラス

```kotlin
import org.springframework.data.jpa.domain.support.AuditingEntityListener
import javax.persistence.*

@EntityListeners(AuditingEntityListener::class)
@Entity
@Table(name = "greeting")
data class Greeting(
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id")
        var id: Long = 0,

        @Column(name = "value")
        val value: String = ""
)
```

# 実行順序の指定
複数のCommandLineRunnerを実装したクラスをDIコンテナへ登録した際に、各クラスの実行順序を@Orderで指定できる。下記のように@Orderの引数で実行順序を指定する。

```kotlin
import com.example.springsecuritydemo.domain.Greeting
import com.example.springsecuritydemo.repository.GreetingRepository
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.CommandLineRunner
import org.springframework.context.annotation.Profile
import org.springframework.core.annotation.Order
import org.springframework.stereotype.Component

@Component
@Order(1)
@Profile(value = ["dev"])
class DevDataInitializer(@Autowired private val greetingRepository: GreetingRepository) : CommandLineRunner {

    private val logger = LoggerFactory.getLogger(javaClass)

    override fun run(vararg args: String?) {

        logger.info("${this.javaClass.simpleName} Run")
        greetingRepository.save(Greeting(value = "Dev!!!"))
    }
}
```

```kotlin
import com.example.springsecuritydemo.domain.Greeting
import com.example.springsecuritydemo.repository.GreetingRepository
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.CommandLineRunner
import org.springframework.context.annotation.Profile
import org.springframework.core.annotation.Order
import org.springframework.stereotype.Component

@Component
@Order(2)
@Profile(value = ["dev"])
class DevDataInitializer2(@Autowired private val greetingRepository: GreetingRepository): CommandLineRunner {

    private val logger = LoggerFactory.getLogger(javaClass)

    override fun run(vararg args: String?) {


        logger.info("${this.javaClass.simpleName} Run")
        greetingRepository.save(Greeting(value = "Dev2!!!"))
    }
}

```

起動時のログを見ると、指定した順序で実行されていることがわかる。
![pic2.png](https://qiita-image-store.s3.amazonaws.com/0/83184/24e0b720-7956-9c50-d9bd-b7b0d6e45770.png)