1. はじめに
Spring Boot で、コンソールアプリケーションを作る方法のメモです。
Spring Boot はWebアプリケーションを作るためによく使われますが、コンソールアプリケーションも作れます。
今回は、コンソール上で標準出力に「Hello World!」と出力して終了するだけの単純なアプリを作ります。
完成品のサンプルアプリは、Githubで公開しています。
github.com
Webアプリを作る場合とほとんど変わりませんが、1箇所だけ、Webアプリを作る場合と違う書き方をする必要があります。
2. 前提
3. 作り方
3.1 プロジェクトの雛形を作る
Spring Initializrで雛形を作る(https://start.spring.io/)。
もしくは私がGithubで公開しているものを clone しても問題ありません。
git clone https://github.com/YuukiYg/sample-springboot-console
3.2 pomを編集する
dependency に「spring-boot-starter-web」や「spring-boot-starter-web-services」が入っている場合は消してください。
これが入っていると、起動した際に、Webアプリとして認識されてしまい、組み込みTomcatが立ち上がってしまいます。
コンソールアプリを作る場合は、「spring-boot-starter」を使用します。
dependencies の例は以下のとおりです。
pom.xml 内のdependenciesタグの例
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
3.3 コーディング
コーディングしていきます。
今回は、コンソールアプリケーションだけど、DIを使ってSpringっぽく作りたいと思います。ビジネスロジックと、それを呼び出すmainメソッドの依存関係を、DIで取り除くようなイメージです。
■ビジネスロジックのインタフェースを作成
ビジネスロジックは、sayHello() という単純なメソッドだけを持つものにしたいと思います。
HelloComponent.java
public interface HelloService { public void sayHello(); }
■ビジネスロジックのインタフェースの実装クラスを作成
先ほど作ったインタフェースの実装部分です。
sayHello()メソッドは、単純に標準出力に「Hello World!」と出力するだけのものです。
ポイントとしては、@Component アノテーションをクラスに付与してください。
こうすることで、アプリケーション起動時のコンポーネントスキャンによって、このクラスが自動でインスタンス化(JavaBean化)され、SpringのDIコンテナに登録され、別クラス(後述のmainクラス)から使用できるようになります。
※DIコンテナは、ApplicationContextとも言います。
HelloComponentImpl.java
@Component public class HelloServiceImpl implements HelloService{ @Override public void sayHello() { System.out.println("Hello World!"); } }
■mainクラスの作成
最後に、mainメソッドを持つクラスを作成します(作成というより、Spiring Initializrを使用したのであれば、クラスの雛形が自動生成されているはずです)。
サンプルコードは以下のとおりです。ポイントは後述します。
SampleSpringbootConsoleApplication.java
@SpringBootApplication // ポイント1 public class SampleSpringbootConsoleApplication { public static void main(String[] args) { // ポイント2 ConfigurableApplicationContext context = SpringApplication.run(SampleSpringbootConsoleApplication.class, args); // ポイント3 HelloService service = context.getBean(HelloService.class); // ポイント4 service.sayHello(); } }
このクラスのポイントは以下のとおりです。
ポイント1
クラスに@SpringBootApplicationを付与する(というより、自動生成されているはずです)。
ポイント2
mainメソッド内で、DIコンテナ(アプリケーションコンテキスト)を取得します。
※このように書く理由は後述します。
ポイント3
取得したDIコンテナから、ビジネスロジックのJavaBeanであるHelloServiceのBeanを取得します。
ポイント4
取得したJavaBeanのビジネスロジックを呼び出します。
参考:ポイント2のように書く理由
例えばよくあるWebアプリだと、
SpringApplication.run(SampleSpringbootConsoleApplication.class, args);
というふうに実行するだけで、組み込みTomcatが立ち上がり、Webサーバとして実行されます(Webサーバが待ち受け状態に入ります)。
しかし今回はコンソールアプリケーションなので、main()メソッドの実行とともにアプリケーションが立ち上がり、ビジネスロジックを実行した後、mainメソッドの終了とともにアプリケーションが終了するように作りたいと思います。
そうなると問題なのが、mainメソッドを持つクラス内で@Injectや@AutowiredによってBeanを受け取ることができないことです。
つまり、以下のように書くことはできないのです。
@SpringBootApplication public class SampleSpringbootConsoleApplication { // このように書いても、mainメソッド内から使用することができない。 @Inject static HelloService helloService; public static void main(String[] args) { SpringApplication.run(SampleSpringbootConsoleApplication.class, args); // ここでヌルポで落ちる。 helloService.sayHello(); } }
したがって、mainメソッドの中でDIコンテナを取得し、取得したDIコンテナからJavaBeanを取得し、mainメソッドの中でそのJavaBeanを使う、というふうに作る必要があります。
3.4 アプリケーションを実行
SampleSpringbootConsoleApplicationをSpring Bootアプリケーションとして実行すれば、以下のようなログが出て、「Hello World!」と出力されているのが確認できると思います。
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.2.0.RELEASE) 2019-11-04 15:16:44.124 INFO 65664 --- [ main] y.s.s.SampleSpringbootConsoleApplication : Starting SampleSpringbootConsoleApplication on Yuuki.local with PID 65664 (/Users/Yuuki/development/sample-springboot-console/target/classes started by Yuuki in /Users/Yuuki/development/sample-springboot-console) 2019-11-04 15:16:44.127 INFO 65664 --- [ main] y.s.s.SampleSpringbootConsoleApplication : No active profile set, falling back to default profiles: default 2019-11-04 15:16:44.593 INFO 65664 --- [ main] y.s.s.SampleSpringbootConsoleApplication : Started SampleSpringbootConsoleApplication in 0.845 seconds (JVM running for 1.482) Hello World!
4.さいごに
以上が、Spring Boot でコンソールアプリケーションを作る方法のメモです。
もっと重厚なアプリケーションを作りたい場合は、Serviceインタフェースと、Serviceインタフェースの実装クラスに、ロジックを書いていけば良いと思います。