Подробное объяснение встроенных событий жизненного цикла SpringBoot Исходный код SpringBoot (10)

Spring Boot
Подробное объяснение встроенных событий жизненного цикла SpringBoot Исходный код SpringBoot (10)

Адрес Github китайского аннотационного проекта SpringBoot:

GitHub.com/Примечания к источнику/…

Эта статья продолжаетАнализ исходного кода механизма мониторинга событий SpringBoot (1) Исходный код SpringBoot (9)

1 Уроки прошлого

Ознакомившись со старым и узнав новое, давайте кратко повторим содержание предыдущей статьи.В предыдущей статье мы разобралиПринцип трансляции событий жизненного цикла при запуске SpringBoot, ключевые шаги теперь сжаты и обобщены:

  1. Подготовьтесь к трансляции встроенных событий жизненного цикла SpringBoot: 1) Сначала загрузитеApplicationListenerКласс реализации слушателя; 2) Затем загрузите класс расширения SPIEventPublishingRunListener.
  2. Использовать при запуске SpringBootEventPublishingRunListenerтранслировать события жизненного цикла, затемApplicationListenerКласс реализации прослушивателя прослушивает соответствующие события жизненного цикла, чтобы выполнить некоторую логическую работу по инициализации.

2 Введение

Предметом прошлой статьи был анализ принципа трансляции событий жизненного цикла при старте SpringBoot, в этой статье мы подробно разберем исходный код семи встроенных событий жизненного цикла в Spring Boot.

3 Анализ исходного кода события жизненного цикла SpringBoot

Чтобы проанализировать события жизненного цикла SpringBoot, давайте сначала посмотрим на диаграмму структуры классов:На приведенном выше рисунке вы можете увидеть взаимосвязь между классами событий:

  1. Родительский класс верхнего уровня является базовым классом событий JDK.EventObject;
  2. Затем базовый класс событий SpringApplicationEventУнаследовал базовый класс событий JDK.EventObject;
  3. Во-вторых, базовый класс событий жизненного цикла SpringBootSpringApplicationEventУнаследовано от базового класса событий Spring.ApplicationEvent;
  4. Наконец, 7 конкретных классов событий жизненного цикла SpringBoot наследуют базовый класс событий жизненного цикла SpringBoot.SpringApplicationEvent.

3.1 Базовый класс событий JDK EventObject

EventObjectКласс является базовым классом событий JDK, который, можно сказать, является основой всех классов событий Java, то есть все классы событий Java прямо или косвенно наследуются от этого класса.Исходный код выглядит следующим образом:

// 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 + "]";
    }
}

можно увидетьEventObjectкласс имеет только одно свойствоsource, это свойство используется для записи того, в каком классе произошло начальное событие, например, оно будет сгенерировано во время процесса запуска SpringBoot.ApplicationStartingEventсобытие, которое изначально было вSpringApplicationиспущенный класс, поэтомуsourceто естьSpringApplicationобъект.

3.2 Базовый класс событий Spring ApplicationEvent

ApplicationEventУнаследовал базовый класс события DKEventObjectclass является базовым классом событий Spring, унаследованным всеми специфическими классами событий Spring, исходный код выглядит следующим образом:

// 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;
	}
}

можно увидетьApplicationEventимеет одно и только одно свойствоtimestamp, который используется для записи времени, когда произошло событие.

3.3 Базовый класс событий SpringBoot SpringApplicationEvent

SpringApplicationEventКласс наследует базовый класс событий Spring.ApplicationEvent, является родительским классом всех встроенных событий жизненного цикла SpringBoot, исходный код выглядит следующим образом:


/**
 * 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;
	}
}

можно увидетьSpringApplicationEventимеет одно и только одно свойствоargs, это свойство является параметром командной строки при запуске SpringBoot, то есть меткой@SpringBootApplicationв стартовом классеmainпараметры функции.

3.4 Класс событий жизненного цикла SpringBoot

Далее давайте посмотримSpringBootВстроенные события жизненного циклаSpringApplicationEventконкретные подклассы .

3.4.1 ApplicationStartingEvent

// ApplicationStartingEvent.java

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

Опубликовано при запуске SpringBootApplicationStartingEventСобытия, время которых публикуется до создания переменной окружения Environment или контейнера ApplicationContext, но после регистрацииApplicationListenerПосле конкретного слушателя флаг флагSpringApplicationНачать загрузку.

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;
	}
}

можно увидетьApplicationEnvironmentPreparedEventеще одно событиеenvironmentАтрибуты, мы могли бы подумать об этом, большеenvironmentКакова роль атрибутов? ответApplicationEnvironmentPreparedEventсобытиеenvironmentФункция атрибута заключается в использовании механизма публикации и подписки на события, и соответствующие прослушиватели могутApplicationEnvironmentPreparedEventСнято с мероприятияenvironmentпеременная, то мы можем написатьenvironmentАтрибут для добавления значения атрибута или чтенияenvironmentзначение в переменной.

Возьмите каштан: ConfigFileApplicationListenerСлушатель слушаетApplicationEnvironmentPreparedEventсобытие, затем выньтеApplicationEnvironmentPreparedEventсобытиеenvironmentимущества, а затем дляenvironmentувеличение атрибутаapplication.propertiesЗначения переменных среды в конфигурационных файлах.

Когда SpringApplication запущен и переменная средыEnvironmentПосле того, как он был создан и является переменной средыEnvironmentНастроил командную строку иServletи другие типы переменных окружения, они будут выпущены в это время.ApplicationEnvironmentPreparedEventмероприятие.

мониторApplicationEnvironmentPreparedEventПервым прослушивателем события являетсяConfigFileApplicationListener,потому чтоConfigFileApplicationListenerСлушатель также должен быть переменной среды.EnvironmentУвеличиватьapplication.propertiesПеременные окружения в конфигурационном файле, после этого некоторые тоже прослушиваютсяApplicationEnvironmentPreparedEventКогда другие слушатели события слушают это событие, вы можете произнести переменную среды в это времяEnvironmentПочти готов.

считать:Слушатели, прослушивающие одно и то же событие, выполняют логику прослушивания по порядку. Мы можем подумать о том, когда эта логика сортировки отсортирована? А почему так отсортировано?

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;
	}
}

можно увидетьApplicationContextInitializedEventбольше событийConfigurableApplicationContextТипcontextАтрибуты,contextФункция атрибута также заключается в том, чтобы соответствующий слушатель мог получить этоcontextСвойство выполняет некоторую логику, конкретная роль будет в3.4.4деталь.

ApplicationContextInitializedEventсобытие вApplicationContextПосле создания контейнера иApplicationContextконтейнер установленenvironmentпеременная и выполняетсяApplicationContextInitializersЗапускается после метода инициализации определения bean-компонента, но до загрузки определения bean-компонента, указывая на то, что ApplicationContext был инициализирован.

Расширение:можно увидетьApplicationContextInitializedEventэто дляcontextконфигурация контейнераenvironmentЗапускается после переменной, в это времяApplicationContextInitializedEventЖдите события, пока естьcontextконтейнер, затем другие потребностиenvironmentСлушатели для переменных среды должны начинаться только сcontextвыигратьenvironmentпеременная, поэтомуApplicationContextInitializedEventНет необходимости настраивать событиеenvironmentАтрибуты.

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;
	}
}

Вы также можете увидетьApplicationPreparedEventбольше событийConfigurableApplicationContextТипcontextнедвижимость, большеcontextФункция атрибута состоит в том, чтобы позволить слушателям, прослушивающим событие, получитьcontextсвойство, слушатель получаетcontextОбычно атрибуты выполняют следующие функции:

  1. уйти с мероприятияcontextсвойства, а затем вы можете добавить некоторые постпроцессоры, такие какConfigFileApplicationListenerСлушатель слушаетApplicationPreparedEventПосле события выньтеcontextпеременная, черезcontextдобавлена ​​переменнаяPropertySourceOrderingPostProcessorэтот постпроцессор;
  2. пройти черезcontextизвлечение атрибутовbeanFactoryконтейнер, затем зарегистрируйте некоторыеbean,НапримерLoggingApplicationListenerслушатель черезApplicationPreparedEventсобытиеcontextизвлечение атрибутовbeanFactoryконтейнер, затем зарегистрированныйspringBootLoggingSystemэтот синглтонbean;
  3. пройти черезcontextизвлечение атрибутовEnvironmentпеременные среды, а затем вы можете манипулировать переменными среды, такими какPropertiesMigrationListener.

ApplicationPreparedEventсобытие вApplicationContextЗапускается, когда контейнер полностью готов, но до его обновления, на данном этапеbeanОпределение было загружено и все ещеenvironmentОн готов к использованию.

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;
	}
}

ApplicationStartedEventСобытие будет обновлено после контейнера, ноApplicationRunnerа такжеCommandLineRunnerизrunСрабатывает перед выполнением метода, флагSpringКонтейнер был обновлен, и на данный момент контейнер готов.

Расширение:упоминается здесьApplicationRunnerа такжеCommandLineRunnerЧто делает интерфейс? Обычно мы будем вSpringПосле обновления контейнера могут быть некоторые статические данные, такие как системные параметры, которые необходимо загрузить в это время, и мы можем реализовать их в это время.ApplicationRunnerилиCommandLineRunnerинтерфейс для реализации загрузки статических данных.

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;
	}
}

ApplicationReadyEventМероприятие называетсяApplicationRunnerа такжеCommandLineRunnerизrunЗапускается после метода, на этот раз флагSpringApplicationуже бежит.

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;
	}
}

можно увидетьApplicationFailedEventВ дополнение к еще одному событиюcontextПомимо атрибутов есть еще одинThrowableТипexceptionСвойство используется для записи исключений, когда SpringBoot не запускается.

ApplicationFailedEventСобытие запускается, когда SpringBoot не удается запустить, указывая на то, что SpringBoot не удалось запустить.

4 Резюме

Эта статья относительно проста и содержит подробный анализ семи событий жизненного цикла, встроенных в SpringBoot. Давайте рассмотрим эти события жизненного цикла и их использование на картинке из предыдущей статьи:

5 в конце

Поскольку некоторые друзья предположили, что некоторые статьи по анализу исходного кода были слишком длинными, что приводило к недостатку терпения и удобочитаемости, поэтому, если статьи по анализу исходного кода в будущем будут слишком длинными, автор рассмотрит возможность их разделения на несколько статей, что быть короче и короче. Теперь это легче читать, хе-хе.

[Примечания к источнику] Адрес Github:

GitHub.com/Примечания к источнику/…