Mastering Spring Boot Startup: CommandLineRunner, ApplicationRunner, Listeners & More
This article explains the five ways Spring Boot can execute code during application startup—including CommandLineRunner, ApplicationRunner, ApplicationListener, @PostConstruct, and InitializingBean—detailing their usage, ordering, argument parsing, and best‑practice recommendations.
Introduction
Sometimes we need to execute code when the application starts, such as logging or certificate checks.
Spring Boot provides at least five ways to run code on startup; this article explains and compares them.
CommandLineRunner
CommandLineRunneris an interface; implementing it runs code after the Spring application has started.
@Slf4j
@Component
@Order(2)
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
log.info("MyCommandLineRunner order is 2");
if (args.length > 0) {
for (int i = 0; i < args.length; i++) {
log.info("MyCommandLineRunner current parameter is: {}", args[i]);
}
}
}
}When a CommandLineRunner bean is found, Spring calls its run() method and passes the command‑line arguments.
Build the jar with mvn clean package and run it with
java -jar springboot-application-startup-0.0.1-SNAPSHOT.jar --foo=bar --name=rgyb. The result shows that arguments are not parsed:
Command‑line arguments are displayed as raw strings; they are not parsed. Use ApplicationRunner for parsing.
If the overridden run() method throws an exception, the application startup aborts.
The @Order annotation determines execution order among multiple runners (lower numbers run first).
⚠️ Do not overuse @Order Excessive ordering indicates hidden dependencies; prefer reducing such coupling.
Summary
If you only need simple space‑separated arguments, MyCommandLineRunner is sufficient.
ApplicationRunner
To parse command‑line options, implement ApplicationRunner. The ApplicationArguments object provides getOptionValues returning a list of values.
@Component
@Slf4j
@Order(1)
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("MyApplicationRunner order is 1");
log.info("MyApplicationRunner Current parameter is {}:", args.getOptionValues("foo"));
}
}Running the jar with
java -jar springboot-application-startup-0.0.1-SNAPSHOT.jar --foo=bar,rgybshows parsed values:
ApplicationRunnercan access ApplicationArguments and retrieve option values as lists.
Exceptions thrown in run() also abort startup. @Order works for ApplicationRunner and shares ordering with CommandLineRunner.
ApplicationListener
If no command‑line parsing is needed, bind startup logic to ApplicationReadyEvent via an ApplicationListener.
@Slf4j
@Component
@Order(0)
public class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
log.info("MyApplicationListener is started up");
}
}The listener runs after all previous startup solutions have completed:
ApplicationReadyEventfires only when the application is fully ready, after other startup mechanisms. @Order can order listeners, but this ordering is independent of runners.
Summary
Use ApplicationListener<ApplicationReadyEvent> for global startup logic without needing command‑line arguments.
@PostConstruct
Another simple way is to annotate a bean method with @PostConstruct, which runs after bean creation but before the container is fully started.
@Component
@Slf4j
@DependsOn("myApplicationListener")
public class MyPostConstructBean {
@PostConstruct
public void testPostConstruct() {
log.info("MyPostConstructBean");
}
}Result shows it runs before the application is ready; ordering with @Order is not reliable because dependencies may be injected later.
Methods annotated with @PostConstruct execute after bean creation and cannot be ordered with @Order.
Use @DependsOn to create explicit dependencies, though it is also discouraged.
Summary
@PostConstructshould be used for initialization of a single bean.
InitializingBean
Implementing InitializingBean and overriding afterPropertiesSet() provides similar behavior to @PostConstruct, but the method is called after all bean properties have been set.
@Component
@Slf4j
public class MyInitializingBean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
log.info("MyInitializingBean.afterPropertiesSet()");
}
}Result shows it runs after property injection, making it safer when the initialization logic depends on @Autowired fields.
⚠️ Difference between @PostConstruct and afterPropertiesSet afterPropertiesSet runs after property injection; @PostConstruct may run before. Therefore afterPropertiesSet avoids NullPointerExceptions caused by missing injections.
Summary
When using constructor injection, both approaches are equivalent.
Source Code Analysis
In SpringApplication.java the callRunners method collects ApplicationRunner and CommandLineRunner beans, sorts them with AnnotationAwareOrderComparator, and invokes each.
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
// get ApplicationRunner beans
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
// get CommandLineRunner beans
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
// sort both types together
AnnotationAwareOrderComparator.sort(runners);
// invoke each runner
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}Reviewing the full SpringApplication source reveals the entire startup process.
Conclusion
A diagram (omitted here) summarizes the relationships among the different startup mechanisms.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
