Institute of technology 003 - six ways to teach you to do something during SpringBoot initialization!

Keywords: Java Spring Boot

preface

In practice, you always need to do some initialization operations when the project starts, such as initializing the thread pool, loading the encryption certificate in advance

So here comes the classic question, which is often asked by interviewers: what are the means to do something when the Spring Boot project starts?

There are many methods. Here are several common methods.

1. Listening container refresh completion extension point applicationlistener < contextrefreshedevent >

The ApplicationContext event mechanism is implemented by the observer design pattern. The ApplicationContext event mechanism is implemented through the ApplicationEvent and ApplicationListener interfaces.

Some built-in events in Spring are as follows:

  1. ContextRefreshedEvent: this event is published when the ApplicationContext is initialized or refreshed. This can also occur using the refresh() method in the ConfigurableApplicationContext interface. Initialization here means that all beans are successfully loaded, post-processing beans are detected and activated, all singleton beans are pre instantiated, and the ApplicationContext container is ready and available.

  2. ContextStartedEvent: this event is published when the ApplicationContext is started using the start() method in the ConfigurableApplicationContext (ApplicationContext sub interface) interface. You can investigate your database, or you can restart any stopped application after receiving this event.

  3. ContextStoppedEvent: this event is published when the ApplicationContext is stopped using stop() in the ConfigurableApplicationContext interface. You can do the necessary cleaning up after receiving this event.

  4. ContextClosedEvent: this event is published when the ApplicationContext is closed using the close() method in the ConfigurableApplicationContext interface. A closed context reaches the end of the life cycle; It cannot be refreshed or restarted.

  5. RequestHandledEvent: This is a Web specific event that tells all beans that HTTP requests have been serviced. Can only be applied to Web applications that use DispatcherServlet. When Spring is used as the front-end MVC controller, the system will automatically trigger this event when Spring finishes processing user requests.

Well, after understanding the above built-in events, we can listen to ContextRefreshedEvent and complete some operations during Spring Boot. The code is as follows:

@Component
public class TestApplicationListener implements ApplicationListener<ContextRefreshedEvent>{
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        System.out.println(contextRefreshedEvent);
        System.out.println("TestApplicationListener............................");
    }
}

Advanced play

You can customize events to meet some specific requirements, such as doing some business processing after the mail is sent successfully.

1. Customize EmailEvent with the following code:

public class EmailEvent extends ApplicationEvent{
   private String address;
   private String text;
   public EmailEvent(Object source, String address, String text){
   super(source);
      this.address = address;
      this.text = text;
   }
   public EmailEvent(Object source) {
     super(source);
   }
   //... setter s and getter s for address and text
}

2. Custom listener with the following code:

public class EmailNotifier implements ApplicationListener{
   public void onApplicationEvent(ApplicationEvent event) {
     if (event instanceof EmailEvent) {
        EmailEvent emailEvent = (EmailEvent)event;
        System.out.println("Email address:" + emailEvent.getAddress());
        System.our.println("Message content:" + emailEvent.getText());
     } else {
        System.our.println("Container itself events:" + event);
     }
   }
}

3. After sending an email, an event is triggered with the following code:

public class SpringTest {
   public static void main(String args[]){
     ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
     //Create an ApplicationEvent object
     EmailEvent event = new EmailEvent("hello","abc@163.com","This is a test");
     //Actively trigger the event
     context.publishEvent(event);
   }
}

2. CommandLineRunner interface of SpringBoot

When the container is initialized, the run() method in CommandLineRunner will be called, which can also complete some things after the container is started. This method is more flexible than ApplicationListener, as follows:

  • Different CommandLineRunner implementations can be implemented through @Order () specify execution order

  • You can receive parameters entered from the console.

The following is a custom implementation class. The code is as follows:

@Component
@Slf4j
public class CustomCommandLineRunner implements CommandLineRunner {

    /**
     * @param args Receive parameters from console
     */
    @Override
    public void run(String... args) throws Exception {
        log.debug("Receive parameters from console>>>>"+ Arrays.asList(args));
    }
}

Run the jar with the following command:

java -jar demo.jar aaa bbb ccc

Three parameters, aaa, bbb and ccc, are passed in the above command. These three parameters will be received by the run() method. As shown below:

Source code analysis

Anyone who has read my article should know how CommandLineRunner is executed Bald series, 23 pictures take you to analyze the Spring Boot startup process from the source code~

The entry of Spring Boot loading context is in the method org.springframework.context.ConfigurableApplicationContext(), as shown in the following figure:

Call CommandLineRunner in callRunners(context, applicationArguments); Execute in this method. The source code is as follows:

3. SpringBoot's ApplicationRunner interface

Both ApplicationRunner and CommandLineRunner are provided by Spring Boot. Compared with CommandLineRunner, it is better to encapsulate the parameters passed in from the console. You can obtain the specified parameters through key value pairs, such as -- version=2.1.0.

Run the jar command as follows:

java -jar demo.jar --version=2.1.0 aaa bbb ccc

The above command passes in four parameters, one key value pair version=2.1.0, and the other three are aaa, bbb and ccc respectively.

It can also be passed @Order () specify priority, as follows:

@Component
@Slf4j
public class CustomApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.debug("Parameters received by the console:{},{},{}",args.getOptionNames(),args.getNonOptionArgs(),args.getSourceArgs());
    }
}

Run through the above command, and the results are as follows:

Source code analysis

Like CommandLineRunner, it is also executed in the callRunners() method. The source code is as follows:

4,@PostConstruct annotation

The first three are for things to be done after the initialization of the container is completed, @PostConstruct This annotation is for doing some things after Bean initialization, such as registering some listeners

@PostConstruct Annotations are usually placed on Bean methods. Once Bean initialization is completed, this method will be called. The code is as follows:

@Component
@Slf4j
public class SimpleExampleBean {

    @PostConstruct
    public void init(){
        log.debug("Bean Initialization complete, call...........");
    }
}

5,@Bean Specifies the initialization method in the annotation

This way and @PostConstruct Similarly, the same method is called after the Bean initialization is completed.

Create a new Bean with the following code:

@Slf4j
public class SimpleExampleBean {

    public void init(){
        log.debug("Bean Initialization complete, call...........");
    }
}

In the configuration class @Bean Instantiate this Bean, but @Bean The initMethod attribute in needs to specify the method to be executed after initialization, as follows:

@Bean(initMethod = "init")
    public SimpleExampleBean simpleExampleBean(){
        return new SimpleExampleBean();
    }

6,   InitializingBean interface

The usage of InitializingBean is basically the same as @PostConstruct Consistent, but the corresponding Bean needs to implement the afterpropertieset method. The code is as follows:

@Slf4j
@Component
public class SimpleExampleBean implements InitializingBean {

    @Override
    public void afterPropertiesSet()  {
        log.debug("Bean Initialization complete, call...........");
    }
}

summary

There are many implementation schemes. The author just summarizes the six commonly used ones and likes them.

Technical exchange QQ group [JAVA,C++,Python,.NET,BigData,AI]: 170933152  
CSDN account: credreamer  
The official account of WeChat is public: credream, and friends who need it can learn from each other.

 

Posted by thestars on Mon, 11 Oct 2021 16:01:16 -0700