preface

In practice, you always need to do some initialization at project startup, such as initializing the thread pool and preloading the encryption certificate…….

So the classic question, which is often asked by interviewers, is: What are some ways to get things done when a Spring Boot project starts up?

There are many ways to do this. Here are some common ones.

1. Listen to the container refresh to complete the extension pointApplicationListener<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 of the built-in events in Spring are as follows:

  1. ContextRefreshedEventThis event is published when ApplicationContext is initialized or refreshed. This can also be used in ConfigurableApplicationContext interface refresh () method to happen. Initialization here means that all beans are successfully loaded, the post-processing beans are detected and activated, all Singleton beans are pre-instantiated, and the ApplicationContext container is ready for use.
  2. ContextStartedEventSon: when using ConfigurableApplicationContext (ApplicationContext interface) start () method in the interface of startup ApplicationContext, the incident was released. You can investigate your database, or you can restart any stopped applications after receiving this event.
  3. ContextStoppedEvent: when using the stop ConfigurableApplicationContext interface () when they stop ApplicationContext release this event. You can do the necessary cleaning up after receiving the event.
  4. ContextClosedEvent: when using ConfigurableApplicationContext close () method in the interface of closed ApplicationContext, the incident was released. A closed context reaches the end of its life cycle; It cannot be refreshed or restarted.
  5. RequestHandledEventThis is a Web-specific event that tells all beans that the HTTP request has been served. This parameter is applicable only to Web applications that use DispatcherServlet. When Spring is used as the front-end MVC controller, the system automatically fires this event when Spring finishes processing the user request.

Now, with these built-in events in mind, we can listen for ContextRefreshedEvent to do something when Spring Boot starts, as follows:

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

Senior play

You can customize events to fulfill specific requirements, such as doing business after a successful email delivery.

  1. To customize EmailEvent, the code is as follows:
public class EmailEvent extends ApplicationEvent{privateString address;privateString text;public EmailEvent(Object source, String address, String text){super(source);this.address = address;thisThe text = text; }public EmailEvent(Object source) {super(source); }/ /... The setter and getter for address and text
}
Copy the code
  1. Custom listener, code as follows:
public class EmailNotifier implements ApplicationListener{public void onApplicationEvent(ApplicationEvent event) {if (event instanceofEmailEvent) {EmailEvent EmailEvent = (EmailEvent)event; System.out.println("Email Address:"+ emailEvent. GetAddress ()); System.our.println("Contents of email:"+ emailEvent. GetText ()); }else{System. Our println ("Container event:"+ event); }}}Copy the code
  1. 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 objectEmailEvent event =new EmailEvent("hello"."[email protected]"."This is a test");// Trigger the eventThe context. PublishEvent (event); }}Copy the code

2,SpringBoottheCommandLineRunnerinterface

The run() method in CommandLineRunner is called when the container is initialized, which also does something after the container is started. This approach is more flexible than ApplicationListener, as follows:

  • differentCommandLineRunnerImplementation can be done through@Order()Specify the order of execution
  • Can receive parameters input from the console.

Here is a custom implementation class, the code is as follows:

@Component
@Slf4j
public class CustomCommandLineRunner implements CommandLineRunner {

    / * * *@paramArgs receives the argument */ passed by the console
    @Override
    public void run(String... args) throws Exception {
        log.debug("Receive parameters from console >>>>"+ Arrays.asList(args)); }}Copy the code

Run the jar with the following command:

java -jar demo.jar aaa bbb ccc
Copy the code

The above command takes three arguments, aaa, BBB, and CCC, which will be received by the run() method. The diagram below:

Source code analysis

CommandLineRunner is an example of how to start a Spring Boot startup from the source code

The entrance to the Spring Boot loading context org. Springframework. Context. ConfigurableApplicationContext () this method, the diagram below:

Call CommandLineRunner in callRunners(Context, applicationArguments); This method is executed in the source code as shown below:

3,SpringBoottheApplicationRunnerinterface

ApplicationRunner and CommandLineRunner are both provided by Spring Boot and are better than CommandLineRunner for encapsulating parameters passed in by the console, which can be obtained by using key-value pairs. For example, version = 2.1.0.

Run the jar command as follows:

java -jar demo.jar --version=2.1. 0 aaa bbb ccc
Copy the code

The above command takes four arguments, one key value pair version=2.1.0, and the other three are aaa, BBB, and CCC.

You can also specify the priority via @order (), as follows:

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

Run the command above, and the result is as follows:

Source code analysis

As with CommandLineRunner, this is also executed in the callRunners() method, as shown below:

4,@PostConstructannotations

The first three are for things to do after the container has been initialized. The @postConstruct annotation is for things to do after the Bean has been initialized, such as registering listeners…

The @postconstruct annotation is placed on the Bean’s method. Once the Bean is initialized, this method will be called as follows:

@Component
@Slf4j
public class SimpleExampleBean {

    @PostConstruct
    public void init(a){
        log.debug("Bean initialization complete, call..........."); }}Copy the code

5. Specify the initialization method in the @bean annotation

This is similar to @postconstruct, which specifies a method to be called after the Bean has been initialized.

Create a new Bean with the following code:

@Slf4j
public class SimpleExampleBean {

    public void init(a){
        log.debug("Bean initialization complete, call..........."); }}Copy the code

The @bean is instantiated in the configuration class, but the initMethod property in the @bean specifies the method to execute after initialization, as follows:

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

6,InitializingBeaninterface

InitializingBean usage is basically the same as @postConstruct, except that the corresponding Bean needs to implement the afterPropertiesSet method as follows:

@Slf4j
@Component
public class SimpleExampleBean implements InitializingBean {

    @Override
    public void afterPropertiesSet(a)  {
        log.debug("Bean initialization complete, call..........."); }}Copy the code

conclusion

There are many implementation schemes, the author just summarized the commonly used six, learn to point a thumbs-up.