Spring boot built-in life cycle event details spring boot source code

Github address of spring boot Chinese annotation project:

https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE

Continued Spring boot event monitoring mechanism source code analysis (I) spring boot source code (IX)

Learn from the past

Let's review the content of the previous article briefly. In the previous article, we analyzed the principle of broadcast life cycle events when SpringBoot was started. Now, we will summarize the key steps:

  1. Prepare for broadcasting spring boot built-in life cycle events: 1) first load the ApplicationListener listener implementation class; 2) second load the SPI extension class eventpublishingrunnistener.
  2. Spring boot uses eventpublishingronlistener to broadcast life cycle events, and then ApplicationListener listener implementation class listens for corresponding life cycle events to perform some initialization logic work.

2 Introduction

The focus of the previous article is to analyze the principle of broadcasting life cycle events when spring boot starts. In this article, we will analyze the source code of seven built-in life cycle events of spring boot in detail.

3 spring boot life cycle event source code analysis

To analyze the life cycle events of SpringBoot, let's first look at a class structure diagram: From the above figure, you can see the relationship between event classes:

  1. The top-level parent class is the event base class EventObject of JDK;
  2. Then the event base class of Spring, ApplicationEvent, inherits the event base class EventObject of JDK;
  3. Secondly, SpringApplicationEvent, the life cycle event base class of SpringBoot, inherits Spring's event base class ApplicationEvent;
  4. Finally, the specific seven life cycle event classes of SpringBoot inherit the life cycle event base class SpringApplicationEvent of SpringBoot.

3.1 event base class EventObject of JDK

EventObject class is the event base class of JDK, which can be said to be the base class of all Java event classes. That is, all Java event classes directly or indirectly inherit from this class. The source code is as follows:

// EventObject.java

public class EventObject implements java.io.Serializable {

    private static final long serialVersionUID = 5516075349620653480L;

    /**
     * The object on which the Event initially occurred.
     */
    protected transient Object  source;
    /**
     * Constructs a prototypical Event.
     *
     * @param    source    The object on which the Event initially occurred.
     * @exception  IllegalArgumentException  if source is null.
     */
    public EventObject(Object source) {
        if (source == null)
            throw new IllegalArgumentException("null source");
        this.source = source;
    }
    /**
     * The object on which the Event initially occurred.
     *
     * @return   The object on which the Event initially occurred.
     */
    public Object getSource() {
        return source;
    }
    /**
     * Returns a String representation of this EventObject.
     *
     * @return  A a String representation of this EventObject.
     */
    public String toString() {
        return getClass().getName() + "[source=" + source + "]";
    }
}

You can see that the EventObject class has only one attribute source, which is used to record which class the initial event occurred in. For example, during the spring boot process, the ApplicationStartingEvent event will be launched, and this event will be launched in the SpringApplication class at first, so the source is the SpringApplication object.

3.2 event base class ApplicationEvent of spring

ApplicationEvent inherits the event base class EventObject class of DK, which is the event base class of Spring. It is inherited by all Spring specific event classes. The source code is as follows:

// ApplicationEvent.java

/**
 * Class to be extended by all application events. Abstract as it
 * doesn't make sense for generic events to be published directly.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 */
public abstract class ApplicationEvent extends EventObject {
	/** use serialVersionUID from Spring 1.2 for interoperability. */
	private static final long serialVersionUID = 7099057708183571937L;
	/** System time when the event happened. */
	private final long timestamp;
	/**
	 * Create a new ApplicationEvent.
	 * @param source the object on which the event initially occurred (never {@code null})
	 */
	public ApplicationEvent(Object source) {
		super(source);
		this.timestamp = System.currentTimeMillis();
	}
	/**
	 * Return the system time in milliseconds when the event happened.
	 */
	public final long getTimestamp() {
		return this.timestamp;
	}
}

You can see that ApplicationEvent has and has only one attribute, timestamp, which is used to record the time of the event.

3.3 event base class of springboot SpringApplicationEvent

The SpringApplicationEvent class inherits the event base class ApplicationEvent of Spring and is the parent class of all Spring boot built-in life cycle events. The source code is as follows:


/**
 * Base class for {@link ApplicationEvent} related to a {@link SpringApplication}.
 *
 * @author Phillip Webb
 */
@SuppressWarnings("serial")
public abstract class SpringApplicationEvent extends ApplicationEvent {
	private final String[] args;
	public SpringApplicationEvent(SpringApplication application, String[] args) {
		super(application);
		this.args = args;
	}
	public SpringApplication getSpringApplication() {
		return (SpringApplication) getSource();
	}
	public final String[] getArgs() {
		return this.args;
	}
}

You can see that SpringApplicationEvent has only one property args, which is the command-line parameter when SpringBoot starts, that is, the parameter of the main function in the @ SpringBootApplication startup class.

3.4 specific life cycle event classes of springboot

Next, let's take a look at the specific subclasses of spring boot built-in life cycle events, namely spring applicationevent.

3.4.1 ApplicationStartingEvent

// ApplicationStartingEvent.java

public class ApplicationStartingEvent extends SpringApplicationEvent {
	public ApplicationStartingEvent(SpringApplication application, String[] args) {
		super(application, args);
	}
}

When SpringBoot starts, the ApplicationStartingEvent event will be published. Its publishing time is before the Environment variable or the container ApplicationContext is created, but after registering the ApplicationListener specific listener, the flag indicates that SpringApplication starts.

3.4.2 ApplicationEnvironmentPreparedEvent

// ApplicationEnvironmentPreparedEvent.java

public class ApplicationEnvironmentPreparedEvent extends SpringApplicationEvent {
	private final ConfigurableEnvironment environment;
	/**
	 * Create a new {@link ApplicationEnvironmentPreparedEvent} instance.
	 * @param application the current application
	 * @param args the arguments the application is running with
	 * @param environment the environment that was just created
	 */
	public ApplicationEnvironmentPreparedEvent(SpringApplication application,
			String[] args, ConfigurableEnvironment environment) {
		super(application, args);
		this.environment = environment;
	}
	/**
	 * Return the environment.
	 * @return the environment
	 */
	public ConfigurableEnvironment getEnvironment() {
		return this.environment;
	}
}

You can see that the ApplicationEnvironmentPreparedEvent event has one more environment attribute. Let's think about what the effect of the environment attribute is? The answer is that the function of the environment attribute of the ApplicationEnvironmentPreparedEvent event is to use the event publish and subscribe mechanism. The corresponding listeners can take the environment variable from the ApplicationEnvironmentPreparedEvent event, and then we can add the attribute value to the environment attribute or read the value in the environment variable.

For example, the ConfigFileApplicationListener listener listens to the ApplicationEnvironmentPreparedEvent event, takes out the environment property of the ApplicationEnvironmentPreparedEvent event, and then adds the environment variable value in the application.properties configuration file for the environment property.

When spring application has started and Environment variable has been created, and Environment variable of command line and Servlet type has been configured for Environment variable, the ApplicationEnvironmentPreparedEvent event will be published.

The first listener listening to the ApplicationEnvironmentPreparedEvent event is ConfigFileApplicationListener, because it is the ConfigFileApplicationListener listener, and the Environment variable in the application.properties configuration file should be added to the Environment variable. Since then, some other listeners also listening to the ApplicationEnvironmentPreparedEvent event event event have listened to this event At this time, it can be said that the Environment variable Environment is almost ready.

Thinking: the listeners listening to the same event perform the listening logic in order. Let's think about when the sorting logic is sorted? Why do you want to sort like this?

3.4.3 ApplicationContextInitializedEvent

// ApplicationContextInitializedEvent.java

public class ApplicationContextInitializedEvent extends SpringApplicationEvent {
	private final ConfigurableApplicationContext context;
	/**
	 * Create a new {@link ApplicationContextInitializedEvent} instance.
	 * @param application the current application
	 * @param args the arguments the application is running with
	 * @param context the context that has been initialized
	 */
	public ApplicationContextInitializedEvent(SpringApplication application,
			String[] args, ConfigurableApplicationContext context) {
		super(application, args);
		this.context = context;
	}
	/**
	 * Return the application context.
	 * @return the context
	 */
	public ConfigurableApplicationContext getApplicationContext() {
		return this.context;
	}
}

It can be seen that the ApplicationContextInitializedEvent event has multiple context properties of ConfigurableApplicationContext type. The function of the context property is also for the corresponding listener to get the context property to perform some logic. The specific function will be detailed in 3.4.4.

After the ApplicationContextInitializedEvent event is created for the ApplicationContext container, the environment variable is set for the ApplicationContext container and the initialization method of ApplicationContextInitializers is executed, but it is triggered before the bean definition is loaded, indicating that ApplicationContext has been initialized.

Extension: It can be seen that ApplicationContextInitializedEvent is triggered after the environment variable is configured for the context container. At this time, as long as there is a context container for events such as ApplicationContextInitializedEvent, other listeners that need the environment variable only need to take the environment variable out of the context, so events such as ApplicationContextInitializedEvent are unnecessary Reconfigure the environment property.

3.4.4 ApplicationPreparedEvent

// ApplicationPreparedEvent.java

public class ApplicationPreparedEvent extends SpringApplicationEvent {
	private final ConfigurableApplicationContext context;
	/**
	 * Create a new {@link ApplicationPreparedEvent} instance.
	 * @param application the current application
	 * @param args the arguments the application is running with
	 * @param context the ApplicationContext about to be refreshed
	 */
	public ApplicationPreparedEvent(SpringApplication application, String[] args,
			ConfigurableApplicationContext context) {
		super(application, args);
		this.context = context;
	}
	/**
	 * Return the application context.
	 * @return the context
	 */
	public ConfigurableApplicationContext getApplicationContext() {
		return this.context;
	}
}

It can also be seen that the ApplicationPreparedEvent event has multiple context properties of ConfigurableApplicationContext type. The purpose of adding the context property is to enable listeners listening to the event to get the context property. Generally, the listener's getting the context property has the following functions:

  1. Take out the context property from the event, and then add some post processors. For example, after the ConfigFileApplicationListener listener listens to the ApplicationPreparedEvent event event, take out the context variable, and add the post processor PropertySourceOrderingPostProcessor through the context variable;
  2. Take out the beanFactory container through the context property, and then register some beans, such as the LoggingApplicationListener listener, take out the beanFactory container through the context property of the ApplicationPreparedEvent event event, and then register the singleton bean springBootLoggingSystem;
  3. Take out the Environment environment variable through the context property, and then you can operate the Environment variable, such as PropertiesMigrationListener.

The ApplicationPreparedEvent event event is triggered when the ApplicationContext container is fully prepared but before the container is refreshed. At this stage, the bean definition has been loaded and the environment is ready to use.

3.4.5 ApplicationStartedEvent

// ApplicationStartedEvent.java

public class ApplicationStartedEvent extends SpringApplicationEvent {
	private final ConfigurableApplicationContext context;
	/**
	 * Create a new {@link ApplicationStartedEvent} instance.
	 * @param application the current application
	 * @param args the arguments the application is running with
	 * @param context the context that was being created
	 */
	public ApplicationStartedEvent(SpringApplication application, String[] args,
			ConfigurableApplicationContext context) {
		super(application, args);
		this.context = context;
	}
	/**
	 * Return the application context.
	 * @return the context
	 */
	public ConfigurableApplicationContext getApplicationContext() {
		return this.context;
	}
}

The ApplicationStartedEvent event will be triggered after the container is refreshed but before the run methods of ApplicationRunner and CommandLineRunner are executed, indicating that the Spring container has been refreshed, and the container is ready.

Extension: what is the function of the application runner and CommandLineRunner interfaces mentioned here? Generally, after the Spring container is refreshed, there may be some static data such as system parameters that need to be loaded. At this time, we can implement the ApplicationRunner or CommandLineRunner interface to load the static data.

3.4.6 ApplicationReadyEvent

// ApplicationReadyEvent.java

public class ApplicationReadyEvent extends SpringApplicationEvent {
	private final ConfigurableApplicationContext context;
	/**
	 * Create a new {@link ApplicationReadyEvent} instance.
	 * @param application the current application
	 * @param args the arguments the application is running with
	 * @param context the context that was being created
	 */
	public ApplicationReadyEvent(SpringApplication application, String[] args,
			ConfigurableApplicationContext context) {
		super(application, args);
		this.context = context;
	}
	/**
	 * Return the application context.
	 * @return the context
	 */
	public ConfigurableApplicationContext getApplicationContext() {
		return this.context;
	}
}

The ApplicationReadyEvent event is triggered after calling the run methods of ApplicationRunner and CommandLineRunner, indicating that SpringApplication is already running.

3.4.7 ApplicationFailedEvent

// ApplicationFailedEvent.java

public class ApplicationFailedEvent extends SpringApplicationEvent {
	private final ConfigurableApplicationContext context;
	private final Throwable exception;
	/**
	 * Create a new {@link ApplicationFailedEvent} instance.
	 * @param application the current application
	 * @param args the arguments the application was running with
	 * @param context the context that was being created (maybe null)
	 * @param exception the exception that caused the error
	 */
	public ApplicationFailedEvent(SpringApplication application, String[] args,
			ConfigurableApplicationContext context, Throwable exception) {
		super(application, args);
		this.context = context;
		this.exception = exception;
	}
	/**
	 * Return the application context.
	 * @return the context
	 */
	public ConfigurableApplicationContext getApplicationContext() {
		return this.context;
	}
	/**
	 * Return the exception that caused the failure.
	 * @return the exception
	 */
	public Throwable getException() {
		return this.exception;
	}
}

You can see that the ApplicationFailedEvent event has not only a context attribute, but also a Throwable type exception attribute to record the exception when the spring boot fails to start.

The ApplicationFailedEvent event is triggered when the spring boot fails to start, indicating that the spring boot fails to start.

4 Summary

This article is relatively simple, and has a detailed analysis of the seven built-in life cycle events of spring boot. Let's also refer to a chart from the previous article to review these life cycle events and their uses:

5 at the end

Because some partners suggested that some source code analysis articles were too long before, resulting in lack of patience and inability to read them. Therefore, if the source code analysis articles are too long later, the author will consider splitting them into several articles, which is shorter and easier to read, hehe.

[source code note] Github address:

https://github.com/yuanmabiji/Java-SourceCode-Blogs

Do something nice, hehe hehe!

The official account [source notes] focuses on the analysis of the source code of the Java backend framework.

Keywords: Programming Spring Java SpringBoot Attribute

Added by bonzie on Tue, 05 May 2020 11:05:49 +0300