How to Run Custom Code at Spring Boot Startup: 8 Implementation Options

This article explains eight ways to execute custom initialization logic during Spring Boot startup, covering CommandLineRunner, ApplicationRunner, ApplicationListener, @EventListener, @PostConstruct, BeanPostProcessor, InitializingBean, SmartInitializingSingleton, and the main method, with code examples and suitable use‑case guidance.

Shepherd Advanced Notes
Shepherd Advanced Notes
Shepherd Advanced Notes
How to Run Custom Code at Spring Boot Startup: 8 Implementation Options

Spring Boot startup initialization mechanisms

CommandLineRunner and ApplicationRunner

Both interfaces are invoked after the application has started. CommandLineRunner receives the raw String[] args and is suitable for simple argument handling. ApplicationRunner receives an ApplicationArguments object, which simplifies parsing complex arguments.

Example:

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("Executing CommandLineRunner logic!");
        for (String arg : args) {
            System.out.println("Startup argument: " + arg);
        }
    }
}

Example:

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("Executing ApplicationRunner logic!");
        if (args.containsOption("debug")) {
            System.out.println("Debug mode enabled!");
        }
    }
}

Typical use: execute logic immediately after the application starts, such as loading caches or registering services.

ApplicationListener for startup events

Implement ApplicationListener<ApplicationReadyEvent> to run code when the application is fully ready.

Example:

import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent> {
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        System.out.println("Application is ready – executing ApplicationReadyEvent logic!");
    }
}

Typical use: perform actions after the application has completely started, such as registering with a monitoring system.

@EventListener annotation

The @EventListener annotation provides a concise way to listen for events without implementing the listener interface.

Example:

import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class MyEventListener {
    @EventListener(ApplicationStartedEvent.class)
    public void onApplicationStarted() {
        System.out.println("ApplicationStartedEvent triggered – custom logic executed!");
    }
}

Typical use: listen to specific events such as application start or shutdown.

@PostConstruct annotation

The standard Java @PostConstruct annotation runs after a bean’s dependencies have been injected and the bean is fully initialized.

Example:

import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;

@Service
public class MyService {
    @PostConstruct
    public void init() {
        System.out.println("@PostConstruct executed after bean initialization!");
    }
}

Typical use: execute logic once a particular bean is ready, such as establishing a database connection.

BeanPostProcessor

Implementing BeanPostProcessor allows insertion of logic before and after any bean’s initialization.

Example:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Before initializing bean: " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("After initializing bean: " + beanName);
        return bean;
    }
}

Typical use: enhance or modify bean initialization globally.

InitializingBean interface

Implementing InitializingBean requires overriding afterPropertiesSet(), which runs after all bean properties have been set.

Example:

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class MyInitializingBean implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("Properties set – afterPropertiesSet() executed!");
    }
}

Typical use: run logic after property injection is complete.

SmartInitializingSingleton interface

This interface’s afterSingletonsInstantiated() method is called once all singleton beans have been created.

Example:

import org.springframework.context.SmartInitializingSingleton;
import org.springframework.stereotype.Component;

@Component
public class MySmartInitializingSingleton implements SmartInitializingSingleton {
    @Override
    public void afterSingletonsInstantiated() {
        System.out.println("All singleton beans initialized – executing afterSingletonsInstantiated()!");
    }
}

Typical use: ensure that logic runs only after the entire application context is fully prepared.

Executing logic in the main method

The main method can contain custom code before and after the call to SpringApplication.run.

Example:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        System.out.println("Custom logic before Spring Boot startup!");
        SpringApplication.run(MyApplication.class, args);
        System.out.println("Custom logic after Spring Boot startup!");
    }
}

Typical use: execute global logic surrounding the entire startup process.

Choosing the appropriate mechanism

Select the mechanism based on when the code must run: immediately after startup ( CommandLineRunner / ApplicationRunner), on specific lifecycle events ( ApplicationListener / @EventListener), after a bean is ready ( @PostConstruct / InitializingBean), after all singleton beans are ready ( SmartInitializingSingleton), or globally around startup ( main method).

Spring Boot lifecycle illustration
Spring Boot lifecycle illustration
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 BootBeanPostProcessorapplicationlistenerPostConstructCommandLineRunnerSmartInitializingSingleton
Shepherd Advanced Notes
Written by

Shepherd Advanced Notes

Dedicated to sharing advanced Java technical insights, daily work snippets, and the power of persistent effort.

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.