Suppose you had a requirement to initialize thread pools, encrypt certificates, and so on during project startup. What would you do? If you don’t have an answer, read on. Here are some ways to do resource initialization in Spring Boot to help you solve and answer this question.

CommandLineRunner

  • Defines the initialization class MyCommandLineRunner

  • Implement the CommandLineRunner interface and implement its run() method, writing the initialization logic in that method

  • Register as a Bean and add the @Component annotation

  • The example code is as follows:

package cn.zh.controller; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Componentpublic class MyCommandLineRunner implements CommandLineRunner { @Override public void run(String... The args) throws the Exception {System. Out. Println (" project initialization -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 11 "); }}Copy the code

A Component that implements the CommandLineRunner interface completes after all Spring Beans are initialized, but before springApplication.run () executes. Let’s verify our test by adding two lines of print.

package cn.zh; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ProcApplication { public static void main(String[] args) { System.out.println("... start SpringApplication.run"); SpringApplication.run(ProcApplication.class,args); System.out.println(".... end SpringApplication.run"); }}Copy the code

ApplicationRunner

  • Define the initialization class MyApplicationRunner

  • Implement the ApplicationRunner interface and implement its run() method, in which you write the initialization logic

  • Register as a Bean and add the @Component annotation

  • The example code is as follows:

package cn.zh.controller; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; @Component public class MyApplicationRunner implements ApplicationRunner { @Override public void Run (ApplicationArguments args) throws Exception {system.out.println (" project initializer 2 ---------"); }}Copy the code

As you can see, both implementing the ApplicationRunner interface and implementing the CommandLineRunner interface can initialize the project to achieve the same effect. The only difference between the two is that the run() method’s inherent parameter is different, in CommandLineRunner it’s just a simple String… The args parameter, while ApplicationRunner contains the ApplicationArguments object, which can help you get richer project information.

@Order

If your project has an initializer that implements the ApplicationRunner interface and an initializer that implements the CommandLineRunner interface, which one will be executed first? The test tells us that the answer is that initializers implementing the ApplicationRunner interface execute first, and I don’t think you need to worry too much about why. But if we need to change the default Order of execution between the two initialization classes, using the @Order annotation can help us solve this problem.

@Component @Order(1) public class MyCommandLineRunner implements CommandLineRunner { /** * Callback used to run the bean. * * @param args incoming main method arguments * @throws Exception on error */ @Override public void run(String...  The args) throws the Exception {System. Out. Println (" project initialization -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 11 "); } } @Component @Order(2) public class MyApplicationRunner implements ApplicationRunner { @Override public void Run (ApplicationArguments args) throws Exception {system.out.println (" project initializer 2 ---------"); } @postConstruct public void init(){system.out.println (" @postconstruct initializable "); }}Copy the code

@PostConstruct

Using the @PostConstruct annotation can also help us initialize resources, as long as it doesn’t depend on other Spring Beans to initialize them.

As you can see the @PostConstruct annotation is used on methods, write a method to test it.

@postConstruct public void init(){system.out.println (" @postconstruct initializable "); }Copy the code
  • Note:

  • Only one non-static method can use this annotation

  • Annotated methods must not have any arguments

  • The annotated method must return void

  • Annotated methods must not throw checked exceptions

  • This method is executed only once

  • In summary, using the @PostConstruct annotation is the fastest way to initialize operations, as long as they don’t depend on other beans being initialized. By adding the @order annotation, we can change the loading Order of different beans across the same hierarchy.

InitializingBean

InitializingBean is an interface provided by Spring that contains only one method afterPropertiesSet(). Spring calls afterPropertiesSet() for a class that implements this interface when its corresponding Bean is managed by Spring and all the necessary properties are set.

@Component public class MyListener1 implements InitializingBean { @Autowired private ShopInfoMapper shopInfoMapper; @override public void afterPropertiesSet() {// Use the beans in the Spring container //System.out.println(shopInfoMapper.selectById("1").getShopName()); System.out.println(" project start OK"); }}Copy the code

ApplicationListener

ApplicationListener is a Spring listener that can be used to listen for events, the typical observer pattern. If there is an ApplicationListener Bean in the container, the ApplicationListener Bean will automatically be triggered whenever the ApplicationContext publishes an ApplicationEvent. Such event mechanisms must be triggered by the program display.

Spring has built-in events that emit certain event actions when certain operations are completed. For example, listen for the ContextRefreshedEvent event, which is triggered when all beans are initialized and successfully loaded. The implementation ApplicationListener interface can receive the listener action and then write its own logic.

Similarly, events can be customized, and listeners can be customized, all according to their own business logic. So you can also do the initial load of resources.

@Component public class MyListener1 implements ApplicationListener { @Override public void OnApplicationEvent (ApplicationEvent ApplicationEvent) {/ / print out the name of each incident System. Out. The println (ApplicationEvent. The toString ()); If (applicationEvent Instanceof ApplicationReadyEvent) {system.out.println (" project start OK"); }}}Copy the code