Run method on Spring Boot startup
Upasana | November 21, 2020 | 3 min read | 15,465 views | spring-boot
Spring Boot provides different mechanisms to run a specific code at Application Startup: ApplicationReadyEvent, CommandLineRunner and ApplicationRunner
Running code on app startup is helpful in many scenarios like initializing DB related stuff, triggering notification about container startup, indexing db entities etc.
There are multiple ways to achieve this in Spring Boot -
-
Using
@Postconstruct
method in singleton bean. -
Using ApplicationEvent - ApplicationReadyEvent or ContextRefreshEvent.
-
Using CommandLineRunner
-
Using ApplicationRunner
1. @PostConstruct
The PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization.
The init()
method will not be called until any autowiring is done for the bean service
.
@Component
public class Monitor {
@Autowired
private SomeService someService;
@PostConstruct
public void init(){
// initialize your monitor here, instance of someService is already injected by this time.
}
}
Be noted that this method must not have any parameters.
2. CommandLineRunner
CommandLineRunner can be used to run code at application startup, provided it should be contained within SpringApplication
. So if you are running program from a war file hosted inside a servlet container (instead of spring boot embedded containers), there may be problems.
Using Bean style approach:
@SpringBootApplication
public class Application {
private static final Logger log = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
@Bean
public CommandLineRunner demo(CustomerRepository repository) {
return (args) -> {
// save a couple of customers
};
}
}
Instead of creating a Bean
, we can define a component
for CommandLineRunner
:
@Component
public class CommandLineAppStartupRunner implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(CommandLineAppStartupRunner.class);
@Override
public void run(String...args) throws Exception {
logger.info("Application started with command-line arguments: {} . \n To kill this application, press Ctrl + C.", Arrays.toString(args));
}
}
The advantage of defining a component is that we can specify the Order
in which multiple such components run.
3. ApplicationRunner
CommandLineRunner does not provide access to ApplicationArguments
, if we need access to access to ApplicationArguments
instead of raw string array, then we can use ApplicationRunner
.
@Component
public class ApplicationRunnerBean implements ApplicationRunner {
@Override
public void run(ApplicationArguments arg0) throws Exception {
System.out.println("ApplicationRunnerBean");
}
}
4. ApplicationReadyEvent in Spring Boot
Spring framework publishes event for ApplicationReadyEvent
, which gets fired when the application is ready to service requests.
@EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() {
System.out.println("hello world, I have just started up");
}
SmartInitializingSingleton Callback interface triggered at the end of the singleton pre-instantiation phase during BeanFactory
bootstrap.
@Bean
public SmartInitializingSingleton importProcessor() {
return () -> {
doStuff();
};
}
Order of execution for multiple startup beans
Multiple CommandLineRunner
/ApplicationRunner
beans can be made to execute in a certain order at app startup using @Order
annotation.
The bean with lowest order value will have the highest priority and hence will run before beans with higher order value. Default order value is Integer.MAX_VALUE
which has lowest PRECEDENCE
, hence will run in the last.
In the below code, CmdAppStartupRunner1
will run first and then CmdAppStartupRunner2
@Order(1)
@Component
public class CmdAppStartupRunner1 implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(CmdAppStartupRunner1.class);
@Override
public void run(String... args) {
logger.info("Application started with command-line arguments: {} . " +
"\n To kill this application, press Ctrl + C.", Arrays.toString(args));
}
}
@Order(2)
@Component
public class CmdAppStartupRunner2 implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(CmdAppStartupRunner2.class);
@Override
public void run(String... args) {
logger.info("Application started with command-line arguments: {} . " +
"\n To kill this application, press Ctrl + C.", Arrays.toString(args));
}
}
CmdAppStartupRunner1
will be executed before CmdAppStartupRunner2
.
Top articles in this category:
- Setting a Random Port in Spring Boot Application at startup
- Running Spring Boot app as a service in unix
- Custom banner in spring boot
- Spring Boot multipart file upload server
- Spring Boot 2.0 Reactive Web Performance Metrics
- Redis rate limiter in Spring Boot
- Sendgrid Dynamic Templates with Spring Boot