skip to content

What are CommandLineRunner and ApplicationRunner in Spring Boot, and when do they run?

level: juniorimportance: must knowfreq 65%

answer

  1. single run() method beans
  2. called after context refresh
  3. web server already started
  4. exception aborts startup
  5. raw args vs parsed ApplicationArguments

basics

~10 s

They are interfaces with a single run() method. Spring Boot calls every such bean once at startup, after the application context is fully built, so you can run one-off initialization code.

solid answer

~40 s

Both are functional callback interfaces you implement as Spring beans. Spring Boot detects all of them and invokes their run() method once, near the end of SpringApplication.run(), after the ApplicationContext is refreshed and all beans (and the embedded web server) are started. Use them for one-off startup work: seeding data, warming caches, logging config, kicking off a job. The only difference is the argument: CommandLineRunner.run(String... args) receives the raw command-line strings, while ApplicationRunner.run(ApplicationArguments args) receives a parsed wrapper that separates --option flags from plain arguments. Any exception thrown from a runner aborts application startup. They are ideal when you need the fully-wired context (injected beans, datasources) available before your code runs, which a bean constructor or @PostConstruct cannot always guarantee.

code

java · 19 lines
java
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class DataSeeder implements CommandLineRunner {

    private final UserRepository users;

    public DataSeeder(UserRepository users) {
        this.users = users; // fully injected by the time run() is called
    }

    @Override
    public void run(String... args) {
        if (users.count() == 0) {
            users.save(new User("admin"));
        }
    }
}

go deeper

for a junior

Know they run once at startup and hold a single run() method; name at least one use case like data seeding.

for a middle

Explain the exact lifecycle position (after refresh, before ApplicationReadyEvent) and the argument-type difference.

for a senior

Contrast with @PostConstruct, note the web server is already up, and that exceptions abort startup.

for a principal

Discuss readiness implications, ordering across both interface types, and when an ApplicationReadyEvent listener is a better fit.

## What they are `CommandLineRunner` and `ApplicationRunner` are two single-method (functional) interfaces provided by Spring Boot (package `org.springframework.boot`). You implement one of them, register the implementation as a Spring bean (e.g. annotate the class `@Component`, or return one from an `@Bean` method), and Spring Boot will automatically call it once during startup. - `CommandLineRunner` has `void run(String... args) throws Exception` — it receives the **raw** command-line arguments exactly as passed to `main`. - `ApplicationRunner` has `void run(ApplicationArguments args) throws Exception` — it receives a **parsed** `ApplicationArguments` object that already separates option flags (`--name=value`) from plain arguments. ## When they run (the lifecycle) Inside `SpringApplication.run(...)` the sequence is roughly: create the `ApplicationContext` → **refresh** it (instantiate all singleton beans, run `@PostConstruct`, start `SmartLifecycle` beans **including the embedded Tomcat/Netty web server**) → then Spring Boot calls a method named `callRunners` which finds every `ApplicationRunner` and `CommandLineRunner` bean and invokes `run()` on each → finally publishes `ApplicationReadyEvent` and returns from `run()`. So when your runner executes, the context is fully wired: every bean is constructed, dependency injection is done, `DataSource`s are live, and the HTTP port is already open. This is the key reason to use a runner instead of a constructor or `@PostConstruct`: you are guaranteed the whole application is assembled. ## Why not a constructor or @PostConstruct? A bean constructor or `@PostConstruct` runs while the context is still being built — other beans you depend on transitively may not be fully initialized, and the web server is not yet started. Runners run strictly after refresh completes, giving you the safest, fully-ready state. ## Gotchas - **Exceptions abort startup.** If `run()` throws, `callRunners` rethrows it, `SpringApplication.run` fails, the context is closed, and the JVM exits with a failure code. A runner is effectively part of your startup contract. - **The web server is already accepting requests** by the time runners run (it starts during context refresh). So a runner is not a safe place to gate traffic — see readiness discussion in advanced material. - They run **once**, synchronously, on the main thread, before `run()` returns. ## When to use Data seeding, cache warm-up, printing effective configuration, verifying external connectivity, or launching a background scheduler/CLI task once the app is ready.

  • Why might you prefer a runner over @PostConstruct for startup work?
    A runner executes after the entire context is refreshed and the web server is started, so all beans and infrastructure are guaranteed ready. @PostConstruct fires mid-construction, when the rest of the context may not be fully initialized.
  • What happens if a runner throws an exception?
    The exception propagates out of callRunners and SpringApplication.run fails; the context is closed and the application exits with a non-zero code. Startup is aborted.

saying these in an interview costs you the question

  • Claiming runners execute periodically or on every request rather than once at startup
  • Saying they run before beans are constructed
  • Thinking an exception in a runner is silently ignored

context