Spring Boot
Running Code
Application Start
Java Development
Code Execution

Running code after Spring Boot starts

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Spring Boot gives you several hooks for running code during or after application startup, but the right hook depends on what "after startup" actually means in your application. Some code should run once the application context is ready, while other code should wait until the app is fully started and ready to serve requests.

Use CommandLineRunner or ApplicationRunner for Startup Tasks

The most common startup hooks are CommandLineRunner and ApplicationRunner. Both run after the application context has been created.

java
1import org.springframework.boot.CommandLineRunner;
2import org.springframework.stereotype.Component;
3
4@Component
5public class StartupRunner implements CommandLineRunner {
6    @Override
7    public void run(String... args) {
8        System.out.println("Application context is ready");
9    }
10}

CommandLineRunner is simple and gives you raw argument strings. ApplicationRunner is similar, but it exposes parsed ApplicationArguments.

java
1import org.springframework.boot.ApplicationArguments;
2import org.springframework.boot.ApplicationRunner;
3import org.springframework.stereotype.Component;
4
5@Component
6public class AppStartupRunner implements ApplicationRunner {
7    @Override
8    public void run(ApplicationArguments args) {
9        System.out.println("Non-option args: " + args.getNonOptionArgs());
10    }
11}

If you care about command-line options, ApplicationRunner is usually more expressive.

Use ApplicationReadyEvent When You Need Full Readiness

Sometimes you do not just want the context initialized. You want the application to be fully started and ready. In that case, listening for ApplicationReadyEvent is often the better hook.

java
1import org.springframework.boot.context.event.ApplicationReadyEvent;
2import org.springframework.context.event.EventListener;
3import org.springframework.stereotype.Component;
4
5@Component
6public class ReadyListener {
7    @EventListener(ApplicationReadyEvent.class)
8    public void onReady() {
9        System.out.println("Application is fully ready");
10    }
11}

This is a good place for tasks such as warm-up calls, readiness notifications, or deferred initialization that should happen only after the app has reached its running state.

Choose the Hook Based on the Work

A practical guideline is:

  • use CommandLineRunner or ApplicationRunner for one-time startup logic tied to bootstrapping
  • use ApplicationReadyEvent for work that should happen only when the app is fully up
  • avoid putting heavy blocking logic in early startup if it delays application availability unnecessarily

That distinction matters for operational behavior. A heavy startup runner can slow down deployments, health checks, and container readiness.

Order and Failure Behavior Matter

If multiple runners exist, ordering can matter. Spring lets you use @Order or implement Ordered so one runner executes before another.

java
1import org.springframework.core.annotation.Order;
2import org.springframework.stereotype.Component;
3import org.springframework.boot.CommandLineRunner;
4
5@Component
6@Order(1)
7public class FirstRunner implements CommandLineRunner {
8    @Override
9    public void run(String... args) {
10        System.out.println("runs first");
11    }
12}

Also remember that exceptions thrown from startup code can fail the application startup entirely. That may be exactly what you want for critical initialization, but it should be a deliberate decision.

Keep Startup Work Small and Observable

Startup hooks are tempting places to hide miscellaneous logic. Resist that. If the application must load caches, seed data, or contact external systems, log clearly, measure duration, and decide whether failures should stop boot or merely warn.

This makes startup behavior operationally understandable instead of mysterious.

If the startup work is slow but noncritical, consider handing it off to a background mechanism rather than tying it directly to startup readiness. That keeps deployments faster while still letting the task run under controlled logging and monitoring.

Common Pitfalls

Using a runner for long blocking work can make the application appear hung during deployment.

Confusing "context created" with "application fully ready" leads to the wrong lifecycle hook.

Packing many unrelated tasks into one large startup method makes failures harder to isolate.

Summary

  • Use CommandLineRunner or ApplicationRunner for ordinary startup tasks.
  • Use ApplicationReadyEvent when the code should run only after full application readiness.
  • Keep startup work intentional, observable, and appropriately ordered.
  • Decide explicitly whether startup-task failure should stop the whole application.

Course illustration
Course illustration

All Rights Reserved.