preface

This section continues with listeners.

Listener mode in Spring Boot

The first event

The first event published is in the run method:

public ConfigurableApplicationContext run(String... args) {
        / /.....................
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        configureHeadlessProperty();
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting();
    / /.....................
    }
Copy the code

Then we go into the getRunListeners(ARgs) method.

    private SpringApplicationRunListeners getRunListeners(String[] args) { Class<? >[] types =newClass<? >[] { SpringApplication.class, String[].class };return new SpringApplicationRunListeners(logger,
                getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
    }
Copy the code

Again saw the familiar getSpringFactoriesInstances method, we went to the spring. See the factoris SpringApplicationRunListener:

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
Copy the code

Well, there’s only one implementation.

We will enter the new SpringApplicationRunListeners () method:

    SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
        this.log = log;
        this.listeners = new ArrayList<>(listeners);
    }
Copy the code

This is obviously the EventPublishingRunListener assigned to the listeners.

Return to the main run() method and call listeners. Starting (); :

// SpringApplicationRunListeners # starting()
public void starting(a) {
        for (SpringApplicationRunListener listener : this.listeners) { listener.starting(); }}Copy the code

The listeners are traversed here, calling starting(). Events as we know, is a EventPublishingRunListener listener.

So we go into the EventPublishingRunListener# starting () method:

    @Override
    public void starting(a) {
        this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
    }
Copy the code

Ojbk, we finally see the action of publishing the event.

Let’s see who’s listening to it:

Saw a listener in the configuration file: LoggingApplicationListener, the name must be related to the log.

This class is too long to post. This class is the logging system used to launch Spring Boot.

Class notes:

An ApplicationListener to configure LoggingSystem. If the environment contains the logging.config attribute, it will be used to boot the logging system, otherwise the default configuration will be used.

Event when Spring Boot starts

  • ApplicationStartingEvent

    Sent when the Spring Boot application starts running before container initialization is complete.

    // SpringApplication # run(String... args) # 301-302
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    Copy the code
  • ApplicationEnvironmentPreparedEvent

    Send before the Spring context is created, because the environment is required to create the Spring context.

    // SpringApplication # prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) # 342
    listeners.environmentPrepared(environment);
    Copy the code
  • ApplicationContextInitializedEvent

    The Spring context is ready and the initializer is called. But Bean Definitions has not been loaded yet.

    // SpringApplication # prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) # 368listeners.contextPrepared(context);
    Copy the code
  • ApplicationPreparedEvent

    The Bean Definitions have been loaded and sent before context refresh.

    // SpringApplication # prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) # 387listeners.contextLoaded(context);
    Copy the code
  • ApplicationStartedEvent

    The Spring context is refreshed before runners are called.

    // SpringApplication # run(String... args) # 318listeners.started(context);
    Copy the code
  • ApplicationReadyEvent

    Runners is called, indicating that Spring Boot is ready.

    // SpringApplication # run(String... args) # 327listeners.running(context);
    Copy the code
  • ApplicationFailedEvent

    Send this event when a startup exception occurs.

    // SpringApplication # handleRunFailure(ConfigurableApplicationContext context, Throwable exception,Collection<SpringBootExceptionReporter> exceptionReporters, SpringApplicationRunListeners listeners) # 794listeners.failed(context, exception);
    Copy the code

Practice listener

  1. Listener definition

    We are defined by imitating LoggingApplicationListener.

    public class OneListener implements GenericApplicationListener {    @Override    public boolean supportsEventType(ResolvableType eventType) {        return eventType.isAssignableFrom(ApplicationStartingEvent.class);    }    @Override    public void onApplicationEvent(ApplicationEvent event) {        System.out.println("yes,I am listening to you.");    }    @Override    public int getOrder(a) {        return Ordered.HIGHEST_PRECEDENCE + 20 +1;    }}
    Copy the code
  2. Listener registration

    1. Configuration to the spring. The factories

      org.springframework.context.ApplicationListener=\ com.example.indepthspringboot.springbootlistener.OneListener
      Copy the code

    2. Hardcoded add

    3. The application.properties property configures context.listener.classes

      These are similar to initializers. There is no repetition.

    4. @ Component annotation

      But it can only be used for events after the container has been created. Because the class is not loaded before the container is created.

      @Componentpublic class TwoListener implements GenericApplicationListener {    @Override    public boolean supportsEventType(ResolvableType eventType) {        return eventType.isAssignableFrom(ApplicationStartedEvent.class);    }     @Override    public void onApplicationEvent(ApplicationEvent event) {        System.out.println("Yes, I am registered. And, I am listening to ApplicationStartedEvent");    }}
      Copy the code

      We then change the listener event to ApplicationStartingEvent.Oh dear, no listening succeeded.

conclusion

Listeners in Spring Boot are actually quite complex. We have just selected some of them here.

First general ground leads again, understand its probably principle, when looking deeply again so later, also won’t make fear.

Browsing through the listener section of Spring Boot, there are a few things to learn:

  • Learned about the practical application of the listener pattern.
  • Extended use of the listener pattern.
  • Listening events can also be represented by generics