Six Ways to Run Code on Spring Boot Startup: Listeners, Runners, and Annotations
This article explains six practical techniques for executing custom logic during Spring Boot startup, covering ApplicationListener events, CommandLineRunner, ApplicationRunner, @PostConstruct, @Bean initMethod, and InitializingBean, with code examples and brief analysis of each approach.
Startup Initialization Techniques in Spring Boot
Spring Boot provides several mechanisms to execute custom logic after the ApplicationContext is fully initialized. The following approaches are commonly used in production code and interview settings.
1. Listening to ContextRefreshedEvent with ApplicationListener
The Spring event system follows the observer pattern. Built‑in events include: ContextRefreshedEvent: Published after all bean definitions are loaded, post‑processors are applied, and singleton beans are pre‑instantiated. ContextStartedEvent: Published when ConfigurableApplicationContext.start() is invoked. ContextStoppedEvent: Published when ConfigurableApplicationContext.stop() is invoked. ContextClosedEvent: Published when the context is closed. RequestHandledEvent: Web‑specific event indicating an HTTP request has been processed.
Implementing ApplicationListener<ContextRefreshedEvent> allows you to run code right after the container is ready:
@Component
public class StartupListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// custom initialization logic here
System.out.println("Context refreshed: " + event);
}
}Custom Events
You can define your own event class extending ApplicationEvent and publish it from any bean. A listener can react to the custom event while still handling standard container events.
public class EmailEvent extends ApplicationEvent {
private final String address;
private final String text;
public EmailEvent(Object source, String address, String text) {
super(source);
this.address = address;
this.text = text;
}
public String getAddress() { return address; }
public String getText() { return text; }
} @Component
public class EmailNotifier implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof EmailEvent) {
EmailEvent e = (EmailEvent) event;
System.out.println("Email to: " + e.getAddress());
System.out.println("Content: " + e.getText());
} else {
System.out.println("Container event: " + event);
}
}
} public class Demo {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
ctx.publishEvent(new EmailEvent("source", "[email protected]", "Welcome"));
}
}2. Implementing CommandLineRunner
Beans that implement CommandLineRunner have their run(String... args) method invoked after the context is refreshed. This is useful for tasks that need command‑line arguments.
@Component
@Slf4j
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
log.debug("Command line arguments: {}", java.util.Arrays.asList(args));
// place initialization code here
}
}Run the application with arguments:
java -jar myapp.jar aaa bbb cccThe three arguments are passed to the run method. Spring Boot triggers all CommandLineRunner beans from the internal method callRunners(context, applicationArguments) during startup.
3. Implementing ApplicationRunner
ApplicationRunneris similar to CommandLineRunner but receives an ApplicationArguments object, which parses option‑style arguments (e.g., --version=2.1.0) and non‑option arguments.
@Component
@Slf4j
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
log.debug("Option names: {}", args.getOptionNames());
log.debug("Non‑option args: {}", args.getNonOptionArgs());
log.debug("Raw args: {}", java.util.Arrays.toString(args.getSourceArgs()));
}
}Example execution:
java -jar myapp.jar --version=2.1.0 aaa bbbThe ApplicationArguments instance provides: getOptionNames() – set of option keys (e.g., version). getOptionValues(String name) – list of values for a given key. getNonOptionArgs() – arguments without a leading --.
Like CommandLineRunner, ApplicationRunner beans are executed from callRunners() after the context is ready.
4. Using @PostConstruct
The @PostConstruct annotation marks a method to be called after the bean’s properties have been set and dependency injection is complete. It is executed before the bean is made available to other beans.
@Component
@Slf4j
public class InitBean {
@PostConstruct
public void init() {
log.debug("Bean initialization complete");
}
}5. Declaring an init method with @Bean(initMethod="…")
When defining a bean via @Bean, you can specify an initialization method that Spring will invoke after the bean is instantiated.
@Bean(initMethod = "init")
public SimpleExampleBean simpleExampleBean() {
return new SimpleExampleBean();
}
public class SimpleExampleBean {
public void init() {
// custom init logic
}
}6. Implementing InitializingBean
Implementing InitializingBean and overriding afterPropertiesSet() provides the same lifecycle hook as @PostConstruct, but ties the bean to a Spring‑specific interface.
@Component
@Slf4j
public class InitBean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
log.debug("Bean afterPropertiesSet invoked");
}
}Choosing the Right Mechanism
Event listener ( ApplicationListener<ContextRefreshedEvent> ) : Best when you need to react to the container lifecycle or to custom events published elsewhere.
CommandLineRunner / ApplicationRunner : Ideal for one‑time startup tasks that may depend on command‑line arguments. Use @Order to control execution sequence when multiple runners exist.
@PostConstruct , @Bean(initMethod) , InitializingBean : Suitable for bean‑level initialization that must happen before the bean is used by other components.
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.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
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.
