Help us understand the problem. What is going on with this article?

Spring Bootでコマンドラインアプリを作る時の注意点

More than 3 years have passed since last update.

次の点に注意しましょう。

  • spring-boot-starter-webは使わない
  • 本処理の実装でCommandLineRunnerは使わない(私見)

spring-boot-starter-webは使わない

コマンドラインアプリを作る時にpom.xmlのdependencyにspring-boot-starter-webを使ってはいけません。

spring-boot-starter-webを使ってしまうと、自分ではコマンドラインアプリを作ってるつもりでも、起動するとWebサーバーが立ち上がってしまいます。ログを注意して見ればWebサーバーを起動しているのがわかるはずです。

コマンドラインアプリケーションの場合はspring-boot-starterを使いましょう。

pom.xmlの雛形は次のようになります。

pom.xml
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.5.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

本処理の実装でCommandLineRunnerは使わない(私見)

※これは個人的な見解で、はっきりと断定できるものではありません。

よく見かけるサンプルでは、メインクラスをCommandLineRunnerの実装クラスとして作成して、runメソッドにアプリの本処理を書いています。
自分も最初はこういう作り方をするものだと思ってました。

Application.java
@SpringBootApplication
public class Application implements CommandLineRunner {
    public static void main(String[] args) {
        System.out.println("main()");
        SpringApplication.run(Application.class, args);
    }
    @Override
    public void run(String... args) throws Exception {
        System.out.println("処理開始");
        //アプリの処理
        System.out.println("処理終了");
    }
}

しかし、この使い方だとJUnitを使う時に問題が生じます。

次のような空のテストメソッドを作成して実行してみます。

ApplicationTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
public class ApplicationTest {
    @Test
    public void test() {
    }
}
実行結果
:
処理開始
処理終了
:

なんということでしょう。呼び出してもいないアプリの本処理が実行されてしまうではありませんか。
これではRepositoryクラスなどのコンテナからインスタンスを取得してテストするケースで毎回本処理が実行されてしまい、厄介なことになります。

なので、本処理の実装にCommandLineRunnerを使うのはやめて、次のようにmainメソッドから本処理を自分で呼び出すようにしましょう。

Application.java
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        System.out.println("main()");
        try (ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args)) {
            Application app = ctx.getBean(Application.class);
            app.run(args);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void run(String... args) throws Exception {
        System.out.println("処理開始");
        //アプリの処理
        System.out.println("処理終了");
    }
}

ちなみにSpringBootのドキュメントには次のように書かれています。

22.6 Using the CommandLineRunner

If you want access to the raw command line arguments, or you need to run some specific code once the SpringApplication has started you can implement the CommandLineRunner interface. The run(String…​ args) method will be called on all Spring beans implementing this interface.

CommandLineRunnerを使うのは、

  • コマンドライン引数を参照したいとき
  • 起動時に一度だけ実行したい処理があるとき

と書いてあり、どちらかというと補助的な処理を実装するのが目的のように読み取れます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした