LoginSignup
4
7

More than 3 years have passed since last update.

Spring BootでCommandLineRunnerを使ってはいけない

Last updated at Posted at 2020-08-10

概要

Spring Applicationが起動した後の処理を書く方法として、CommandLineRunnerを使うか、ApplicationRunnerを使うという方法があります。どっちを使えばいいの?と迷うところですが、ApplicationRunnerを推奨します。
Spring Boot Features / 1.10. Using the ApplicationRunner or CommandLineRunner(参考リンク1)

ApplicationRunnerを使う理由(CommandLineRunnerを使ってはいけない理由)

引数の扱いに違いがあります。逆に言うと、引数を使わないアプリケーションであれば、どちらを使っても問題ありません。
例えば、アプリケーションの引数として「arg1 arg2」が設定されている状態で、Webサーバのポートを変えるために、「--server.port=8081」という引数を追加したときに、違いが表れてきます。

実例

どちらも引数を標準出力に表示するプログラムです。

CommandLineRunner

TestCommandLineRunner.java
package com.example.demo;

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class TestCommandLineRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println(" - CommandLineRunner - ");
        for(int i=0; i<args.length; i++) {
            System.out.printf("%s:%s\n", i, args[i]);
        }
    }

}

ApplicationRunner

TestApplicationRunner
package com.example.demo;

import java.util.List;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class TestApplicationRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(" - ApplicationRunner - ");
        List<String> argsList = args.getNonOptionArgs();
        for(int i=0; i<argsList.size(); i++) {
            System.out.printf("%s:%s\n", i, argsList.get(i));
        }
    }

}

args.getNonOptionArgsで、先頭に「--」の付いていない引数のみを取得しています。

実行結果

上記のアプリケーションを、引数「arg1 arg2」で実行した場合の結果は下記の通りです。

 - ApplicationRunner - 
0:arg1
1:arg2
 - CommandLineRunner - 
0:arg1
1:arg2

違いはありません。

実例(引数を追加した場合)

たとえば、Webサーバのポートを変えるために、「--server.port=8081」という引数を追加します。
Spring Boot Features - 2. Externalized Configuration(参考リンク2)

実行結果

上記のアプリケーションを、引数「arg1 arg2 --server.port=8081」で実行した場合の結果は下記の通りです。

 - ApplicationRunner - 
0:arg1
1:arg2
 - CommandLineRunner - 
0:arg1
1:arg2
2:--server.port=8081

ApplicationRunnerの方は結果が変わりませんが、CommandLineRunnerの方は、追加した引数が取れています。Spring Bootの動作を変えるための引数で、アプリケーションでは不要(のはず)なので、「--server.port=8081」の引数は取れない方がよいのではと思います。もちろん、取ることもできます。

System.out.println(args.getOptionValues("server.port"));
=> [8081]

STSで実行すると、「--spring.output.ansi.enabled=always」がargs[0]に入る件

Where is --spring.output.ansi.enabled configured? - Stack Overflow(参考リンク3)
に記載の通り、STSのRun Configurationで「ANSI console output」のチェックが入っていると、自動的に設定される引数のようです。ApplicationRunnerを使っていれば、正しく引数を処理できますね。

動作環境

OpenJDK11.0.2
Spring Boot 2.3.2

参考

  1. Spring Boot Features / 1.10. Using the ApplicationRunner or CommandLineRunner
  2. Spring Boot Features - 2. Externalized Configuration
  3. Where is --spring.output.ansi.enabled configured? - Stack Overflow
4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7