Публичный аккаунт WeChat:студия gmapper
Колонка самородков:glmapper
Вейбо:Сумасшедший Stone_henu
Добро пожаловать, чтобы обратить внимание, учиться и делиться технологиями вместе
в этой статьеПоговорим о механизме расширения в Spring (1)средняя параSpring
Анализируется механизм события. тогда дляSpringBoot
Например, это вSpring
Какие расширения были сделаны на его основе? Поговорим об этом в будущемSpringBoot
события в .
В процессе запуска SpringBoot некоторые классы из spring.factories будут загружаться через механизм SPI, включая классы, связанные с событиями.
- SpringApplicationRunListener
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
- ApplicationListener
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
SpringApplicationRunListener
классSpringBoot
новый класс в .SpringApplication
используйте их в классе для косвенного вызоваApplicationListener
. Еще один новый классSpringApplicationRunListeners
,SpringApplicationRunListeners
содержит несколькоSpringApplicationRunListener
.
SpringApplicationRunListener
SpringApplicationRunListener
интерфейс указываетSpringBoot
жизненного цикла, транслировать соответствующее событие в каждом жизненном цикле, вызывать фактическиеApplicationListener
своего рода. через паруSpringApplicationRunListener
анализа, также возможноSpringBoot
Понимание всего процесса запуска было бы большим подспорьем.
Давайте взглянемSpringApplicationRunListener
Код интерфейса:
public interface SpringApplicationRunListener {
//当run方法首次启动时立即调用。可用于非常早期的初始化。
void starting();
//在准备好环境后,但在创建ApplicationContext之前调用。
void environmentPrepared(ConfigurableEnvironment environment);
//在创建和准备好ApplicationContext之后,但在加载源之前调用。
void contextPrepared(ConfigurableApplicationContext context);
//在加载应用程序上下文后但刷新之前调用
void contextLoaded(ConfigurableApplicationContext context);
//上下文已刷新,应用程序已启动,但尚未调用commandlinerunner和applicationrunner。
void started(ConfigurableApplicationContext context);
//在运行方法完成之前立即调用,此时应用程序上下文已刷新,
//并且所有commandlinerunner和applicationrunner都已调用。
//2.0 才有
void running(ConfigurableApplicationContext context);
//在运行应用程序时发生故障时调用。2.0 才有
void failed(ConfigurableApplicationContext context, Throwable exception);
}
SpringApplicationRunListeners
упомянутый выше,SpringApplicationRunListeners
даSpringApplicationRunListener
коллекция, включающая множествоSpringApplicationRunListener
пример;SpringApplication
Класс фактически используетSpringApplicationRunListeners
класс, сSpringApplicationRunListener
Жизненный цикл тот же, называяSpringApplicationRunListener
. Затем транслируйте соответствующее событие наApplicationListener
.
Подробности смотрите в коде:SpringApplicationRunListeners.
EventPublishingRunListener
EventPublishingRunListener
классSpringApplicationRunListener
Класс реализации интерфейса, который имеет функцию трансляции событий. его внутреннее использованиеApplicationEventMulticaster
Событие публикуется до фактического обновления контекста. Посмотрите нижеEventPublishingRunListener
События, соответствующие жизненному циклу класса.
ApplicationStartingEvent
ApplicationStartingEvent
даSpringBoot
Событие, которое выполняется при запуске автозагрузки, что можно получить в этом событииSpringApplication
объект, вы можете сделать некоторые настройки перед выполнением, соответствующий метод вызоваstarting()
.
ApplicationEnvironmentPreparedEvent
ApplicationEnvironmentPreparedEvent
даSpringBoot
соответствоватьEnviroment
Событие, которое выполняется, когда оно готово, контекст в это времяcontext
Еще не создан. получено в этом монитореConfigurableEnvironment
После этого вы можете выполнять операции с информацией о конфигурации, такие как изменение информации о конфигурации по умолчанию, добавление дополнительной информации о конфигурации и т. д. Соответствующий метод жизненного циклаenvironmentPrepared(environment)
;SpringCloud
, в этот момент инициализируется контекст загрузки.
ApplicationContextInitializedEvent
когдаSpringApplication
и готовApplicationContext
, а при загрузке любогоbean
вызывается перед определениемApplicationContextInitializers
опубликованы события. Соответствующий метод жизненного циклаcontextPrepared()
ApplicationPreparedEvent
ApplicationPreparedEvent
даSpringBoot
контекстcontext
Создание завершено — это публикуемое событие, но на этот разspring
серединаbean
Еще не полностью загружен. Здесь контекст может быть передан для выполнения некоторых дополнительных операций. Но в этом слушателе нет возможности получить кастомныйbean
и работать. Соответствующий метод жизненного циклаcontextLoaded()
.
ApplicationStartedEvent
Это событие было введено в версии 2.0; конкретный выпуск заключается в том, что после обновления контекста приложения любой вызовApplicationRunner
иCommandLineRunner
перед запуском программы.
ApplicationReadyEvent
это иApplicationStartedEvent
Очень похоже, он также вызывается после обновления контекста приложения, разница в том, что в это времяApplicationRunner
иCommandLineRunner
завершил вызов, что также означает, чтоSpringBoot
Загрузка завершена.
ApplicationFailedEvent
SpringBoot
Когда событие выполняется при запуске исключения, когда возникает исключение, лучше всего добавить обработчик, соответствующий виртуальной машине, для повторного использования и высвобождения ресурсов, чтобы информация об исключении могла быть обработана мирным путем.
демо и порядок выполнения каждого события
Распечатаны демо, соответствующие следующим событиям, и порядок выполнения.
- GlmapperApplicationStartingEventListener
public class GlmapperApplicationStartingEventListener implements ApplicationListener<ApplicationStartingEvent> {
@Override
public void onApplicationEvent(ApplicationStartingEvent applicationStartingEvent) {
System.out.println("execute ApplicationStartingEvent ...");
}
}
- GlmapperApplicationEnvironmentPreparedEvent
public class GlmapperApplicationEnvironmentPreparedEvent implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent applicationEnvironmentPreparedEvent) {
System.out.println("execute ApplicationEnvironmentPreparedEvent ...");
}
}
- GlmapperApplicationContextInitializedEvent
public class GlmapperApplicationContextInitializedEvent implements ApplicationListener<ApplicationContextInitializedEvent> {
@Override
public void onApplicationEvent(ApplicationContextInitializedEvent applicationContextInitializedEvent) {
System.out.println("execute applicationContextInitializedEvent ...");
}
}
- GlmapperApplicationPreparedEvent
public class GlmapperApplicationPreparedEvent implements ApplicationListener<ApplicationPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationPreparedEvent applicationPreparedEvent) {
System.out.println("execute ApplicationPreparedEvent ...");
}
}
- GlmapperApplicationStartedEvent
public class GlmapperApplicationStartedEvent implements ApplicationListener<ApplicationStartedEvent> {
@Override
public void onApplicationEvent(ApplicationStartedEvent applicationStartedEvent) {
System.out.println("execute ApplicationStartedEvent ...");
}
}
- GlmapperApplicationReadyEvent
public class GlmapperApplicationReadyEvent implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
System.out.println("execute ApplicationReadyEvent ...");
}
}
- Результаты
Архитектура событий в SpringBoot
здесьSpringApplicationRunListener
Для этого класса. в классе реализацииEventPublishingRunListener
, существует два режима публикации событий:
- пройти через
SimpleApplicationEventMulticaster
транслировать событие - Все слушатели передаются в соответствующие
Context
такEventPublishingRunListener
Не только ответственность за публикацию событий, но и в нужное времяSpringApplication
Полученный слушатель связан с контекстом приложения.
SimpleApplicationEventMulticaster
SimpleApplicationEventMulticaster
даSpring
Транслятор событий по умолчанию. Давайте посмотрим, как это работает:
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
Как вы можете видеть из приведенного выше фрагмента кода, он вызывает каждого слушателя, проходя через каждый зарегистрированный слушатель и запускаяonApplicationEvent
метод.
Давайте посмотрим нижеSimpleApplicationEventMulticaster
Структура интеграции класса:
AbstractApplicationContext
Давайте поговорим об этом, этот класс фактически отвечает за инициализацию системы событий.
Инициализация системы событий
Инициализация системы событий соответствуетSpringBoot
процесс запускаrefreshContext
Сюда;refreshContext
В частности, вызовите метод AbstractApplicationContext.refresh() и, наконец, вызовите initApplicationEventMulticaster(), чтобы завершить инициализацию системы событий. Код выглядит следующим образом:
Пользователи могут определить собственный вещатель событий для контейнера, если реализацияApplicationEventMulticaster
Вот и все,Spring
Он будет зарегистрирован как распространитель событий контейнера через механизм отражения.Если настроенный внешний распространитель событий не найден,Spring
используется по умолчаниюSimpleApplicationEventMulticaster
как ведущий событий.
регистрация на мероприятие
Регистрация событий выполняется после завершения инициализации системы событий, а такжеAbstractApplicationContext.refresh()
вызывается метод.
- Сначала зарегистрируйте статически указанный
listeners
; сюда входят те прослушиватели, которые мы настроили. - перечислить
DefaultListableBeanFactory
серединаgetBeanNamesForType
получить обычайApplicationListener
bean
Зарегистрируйтесь на мероприятия. - Трансляция ранних событий.
трансляция события
Релиз мероприятия сопровождаетсяSpringBoot
Весь жизненный цикл стартапа. Разные этапы соответствуют публикации разных событий. Мы проанализировали каждое событие выше. Давайте посмотрим на реализацию публикации событий:
org.springframework.context.support.AbstractApplicationContext#publishEvent
Событие в EarlyApplicationEvents предназначено для сохранения информации об уведомлении, когда вещатель не установлен.Как только контейнер будет установлен, он будет уведомлен непосредственно в будущем.
Широковещательное событие в конечном итоге вызываетсяApplicationEventMulticaster
изmulticastEvent
реализовать. иmulticastEvent
То есть способ исполнения события.
выполнение события
вышеSimpleApplicationEventMulticaster
Раздел уже представленmulticastEvent
Сюда. добавь если естьtaskExecutor
будет использовать параллельный режим для выполнения событий, но на самом делеSimpleApplicationEventMulticaster
Реализации пула потоков не предусмотрено.По умолчанию события выполняются синхронно (org.springframework.core.task.SyncTaskExecutor
), поэтому, если вам нужна асинхронная конфигурация, вам нужно реализовать пул потоков самостоятельно.
Фаза события в процессе запуска SpringBoot
вернуться сюдаSpringApplication
изrun
метод см.SpringBoot
Что делает каждая фаза события во время запуска.
starting -> ApplicationStartingEvent
здесьdebug
прибытьstarting
метод, восходящий кmulticastEvent
,здесьtype
заApplicationStartingEvent
; соответствующие события таковы:
- LoggerApplicationListener: настроить систему ведения журнала. использовать
logging.config
Конфигурация, указанная переменной среды, или конфигурация по умолчанию - BackgroundPreinitializer: запуск некоторых трудоемких задач инициализации как можно раньше с использованием фонового потока.
- DelegatingApplicationListener: перенаправить в переменные среды после прослушивания событий
context.listener.classes
указанные прослушиватели событий - LiquibaseServiceLocatorApplicationListener: используйте
SpringBoot
исполняемыйjar
Пакеты работают с заменой версийliquibase ServiceLocator
listeners.environmentPrepared->ApplicationEnvironmentPreparedEvent
-
AnsiOutputApplicationListener: согласно
spring.output.ansi.enabled
конфигурация параметровAnsiOutput
-
ConfigFileApplicationListener:
EnvironmentPostProcessor
, читать файлы конфигурации из общепринятых мест, например из следующих каталоговapplication.properties
,application.yml
и другие файлы конфигурации:- classpath:
- file:.
- classpath:config
- file:./config/
Его также можно настроить для чтения файлов конфигурации из других указанных мест.
-
ClasspathLoggingApplicationListener: событие готово для среды
ApplicationEnvironmentPreparedEvent
/применить не удается件ApplicationFailedEvent
ответить на журналDEBUG
выходной уровеньTCCL(thread context class loader)
изclasspath
. -
FileEncodingApplicationListener: прекращает запуск приложения, если кодировка системного файла отличается от указанной в переменной среды. Конкретный метод заключается в сравнении свойств системы
file.encoding
и переменные окруженияspring.mandatory-file-encoding
Они равны (без учета регистра).
listeners.contextPrepared->ApplicationContextInitializedEvent
Связанные слушатели относятся к описанию выше.listeners.contextLoaded->ApplicationPreparedEvent
Связанные слушатели относятся к описанию выше.refresh->ContextRefreshedEvent
- ConditionEvaluationReportLoggingListener: на самом деле реализовано
ApplicationContextInitializer
интерфейс, целью которого являетсяConditionEvaluationReport
Для записи в журнал используйтеDEBUG
выход уровня. Отчет о сбое программы вызывает вывод сообщения, в котором пользователю предлагается отобразить отчет в режиме отладки. Это связано сConditionEvaluationReportListener
прослушиватель событий, а затем вывод, когда происходит соответствующее событиеConditionEvaluationReport
Отчет. - ClearCachesApplicationListener: после загрузки контекста приложения очистить кеш и реагировать на события.
ContextRefreshedEvent
. - SharedMetadataReaderFactoryContextInitializer: Кому
context
зарегистрировалBeanFactoryPostProcessor
:CachingMetadataReaderFactoryPostProcessor
пример. - Ресурсурлпровидер:
handling mappings
иметь дело с
started->ApplicationStartedEvent
Связанные слушатели относятся к описанию выше.running->ApplicationReadyEvent
Связанные слушатели относятся к описанию выше.BackgroundPreinitializer&DelegatingApplicationListener
Эти два проходят через весь процесс, и здесь они объясняются отдельно:
- BackgroundPreinitializer: для некоторых трудоемких задач используйте фоновый поток, чтобы запустить их как можно раньше, чтобы начать выполнение инициализации, что
SpringBoot
поведение по умолчанию. Эти действия по инициализации также можно назвать предварительной инициализацией. Вы можете установить свойства системы,spring.backgroundpreinitializer.ignore
заtrue
Этот механизм можно отключить. Когда этот механизм отключен, соответствующие задачи инициализации выполняются в потоке переднего плана. - DelegatingApplicationListener: прослушивает события приложения и передает эти события приложения свойствам среды.
context.listener.classes
указанные слушатели.
резюме
Уже,SpringBoot
Материалы, связанные с событием, закончились. Эта статья изSpringApplicationRunListener
Начнем с этого класса, а затем представимSpringBoot
Событие, запустившее процесс, и жизненный цикл события. Наконец представилSpringBoot
Эти встроенные прослушиватели соответствуют различным этапам процесса запуска.
В начале нового года поздравляю всех с Новым годом!