← Spring コース
48. SpringApplication.run がやること
に書くのは の1行です。 4.1.1 のソースでは、この中で環境(設定値の集まり)を用意し、 を作り、 で の を生成し、最後に (起動の最後に呼ばれる自分の処理)を呼びます。 が立つのは refresh の途中で、起動ログの各行もこの段階に対応します。
どの種類のコンテキストを作るかは、コードではなくで決まります。同じを Tomcat と の を外して起動すると、種別は SERVLET から NONE に変わり、Tomcat の行は出ず、close を呼ばなくても run が返るとプロセスが終わりました。NestJS では create のあと自分で listen を呼びますが、Boot ではポートを開くかどうかもクラスパスから決まります。
数字の読み方には注意が要ります。Started の行の 0.947 seconds と、その右の process running for 1.105 は別の数で、後者は の起動からの経過です。依存が だけのアプリを展開済みクラスから5回起動した値は 0.718〜0.947 秒でしたが、ファイルがキャッシュに載った状態での値で、依存を足せば変わります。
点線の付いた語はタップすると説明が出ます。用語集を開く →
main: SpringApplication.run(...)自分で書くのはこの1行
ApplicationStartingEvent
環境を用意するprepareEnvironment。引数・環境変数・設定ファイルを集める
ApplicationEnvironmentPreparedEventバナーを表示
コンテキストを作るcreateApplicationContext。決まっている種別に合うコンテキストを作る
SERVLET 用か、Web なしのコンテキストかApplicationPreparedEvent
refreshrefreshContext。singleton の Bean を生成。Tomcat もここで起動
ContextRefreshedEventログ: Started ... in N seconds
Runner を呼ぶcallRunners。CommandLineRunner と ApplicationRunner
直前に ApplicationStartedEventApplicationReadyEvent
run が返る戻り値は作られた ApplicationContext
- ・箱の中の英字は run メソッドの本体に出てくるメソッド名です(Spring Boot 4.1.1 の SpringApplication.java)
- ・種別(SERVLET / NONE)は run の本体より前、SpringApplication のコンストラクタでクラスパスから決まります。上のコードが run の前に種別を印字できるのはそのためです
- ・種別が NONE のときは Tomcat の行が出ません。close を呼ばない main クラスでも、run が返った直後にプロセスが終わりました
- ・run の本体にはこのほかにリスナーの起動や失敗時の処理もあります。段階の数を固定して覚える必要はありません
サンプルコード(フレームワーク環境が必要なため表示のみ)
// EventsApp.java — run の途中で何がどの順に起きるかを印字する
package l15.events;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class EventsApp {
@Bean CommandLineRunner commandLineRunner() {
return args -> System.out.println(">> CommandLineRunner.run args=" + java.util.List.of(args));
}
@Bean ApplicationRunner applicationRunner() {
return args -> System.out.println(">> ApplicationRunner.run nonOptionArgs=" + args.getNonOptionArgs());
}
public static void main(String[] args) {
// SpringApplication.run(EventsApp.class, args) を2行に分けて、間にリスナーを挟んだ形
SpringApplication app = new SpringApplication(EventsApp.class);
System.out.println(">> webApplicationType = " + app.getWebApplicationType());
app.addListeners(event -> System.out.println(">> event: " + event.getClass().getSimpleName()));
ConfigurableApplicationContext ctx = app.run(args);
System.out.println(">> run() returned: " + ctx.getClass().getSimpleName());
ctx.close();
}
}
// Spring Boot 4.1.1 / JDK 25、引数 alpha --flag=1 で起動した出力
// ([log] の行は起動ログ。時刻などを落として短くしてある)
//
// >> webApplicationType = SERVLET
// >> event: ApplicationStartingEvent
// >> event: ApplicationEnvironmentPreparedEvent
// >> event: ApplicationContextInitializedEvent
// [log] Starting EventsApp using Java 25.0.4.1 with PID 1 (...)
// [log] No active profile set, falling back to 1 default profile: "default"
// >> event: ApplicationPreparedEvent
// [log] Tomcat initialized with port 8080 (http)
// [log] Starting service [Tomcat]
// [log] Starting Servlet engine: [Apache Tomcat/11.0.24]
// [log] Root WebApplicationContext: initialization completed in 417 ms
// [log] Tomcat started on port 8080 (http) with context path '/'
// >> event: ServletWebServerInitializedEvent
// >> event: ContextRefreshedEvent
// [log] Started EventsApp in 0.78 seconds (process running for 0.94)
// >> event: ApplicationStartedEvent
// >> event: AvailabilityChangeEvent
// >> CommandLineRunner.run args=[alpha, --flag=1]
// >> ApplicationRunner.run nonOptionArgs=[alpha]
// >> event: ApplicationReadyEvent
// >> event: AvailabilityChangeEvent
// >> run() returned: AnnotationConfigServletWebServerApplicationContext
// (このあとは ctx.close() による終了処理の行)
図やコードに出てくる用語(タップで説明)
サンプルコードで身につける(5本) →
学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。
公式ドキュメントで詳しく ↗