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.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Six Ways to Run Code on Spring Boot Startup: Listeners, Runners, and Annotations

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 ccc

The 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

ApplicationRunner

is 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 bbb

The 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&lt;ContextRefreshedEvent&gt; ) : 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Spring BootApplicationListenerApplicationRunnerPostConstructCommandLineRunner
Code Ape Tech Column
Written by

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

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.