Введение в модель, управляемую событиями
Модель, управляемая событиями, также обычно понимается как модель наблюдателя или модель публикации/подписки.
- отношение «один ко многим» между объектами;
- Когда цель отправляет изменения (опубликовывается), наблюдатели (подписчики) могут получать изменения;
- Как обрабатывает наблюдатель, цели не нужно вмешиваться, и отношения между ними слабо связаны.
Есть много примеров моделей, управляемых событиями, таких как светофоры в жизни и центр конфигурации, который мы используем в микросервисах, Когда конфигурация отправляется, конкретный экземпляр приложения отправляется для обновления контекста Spring.
Механизм событий Spring
Базовые концепты
Модель Spring, управляемая событиями, состоит из трех частей:
- Событие: ApplicationEvent, унаследованное от EventObject JDK, все события будут наследоваться от него и получать источник события через источник.
- Издатель событий: интерфейс ApplicationEventPublisher и ApplicationEventMulticaster, используя этот интерфейс, наш Сервис имеет возможность публиковать события.
- Подписчик событий: ApplicationListener, унаследованный от EventListener JDK, его наследуют все слушатели.
Процесс, управляемый событиями Spring
событие
Spring по умолчанию предоставляет следующие реализации для событий ApplicationEvent:
- ContextStoppedEvent: событие, инициированное после остановки ApplicationContext;
- ContextRefreshedEvent: событие, инициированное после завершения инициализации или обновления ApplicationContext;
- ContextClosedEvent: событие, инициированное после закрытия ApplicationContext. Например, когда веб-контейнер закрывается, автоматически срабатывает отключение контейнера Spring.Если это обычное java-приложение, его нужно вызвать
ctx.registerShutdownHook()
Зарегистрируйте хук при выключении виртуальной машины; - ContextStartedEvent: событие, инициированное после запуска ApplicationContext;
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
//事件发生的时间
private final long timestamp = System.currentTimeMillis();
//创建一个新的ApplicationEvent事件
public ApplicationEvent(Object source) {
super(source);
}
public final long getTimestamp() {
return this.timestamp;
}
}
Базовый класс событийApplicationEvent
, все конкретные события будут наследовать абстрактный класс событий.
прослушиватель событий
ApplicationListener
унаследовано от JDKEventListener
, JDK требует, чтобы все прослушиватели наследовались от него.
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E var1);
}
Предоставляет метод onApplicationEvent для обработкиApplicationEvent
, но обработка конкретных событий требует оценки. иGenericApplicationListener
иSmartApplicationListener
Предоставляет дополнительные метаданные о событии.
public class SourceFilteringListener implements GenericApplicationListener, SmartApplicationListener {
private final Object source;
@Nullable
private GenericApplicationListener delegate;
//为特定事件源创建SourceFilteringListener,并传入代理的监听器类
public SourceFilteringListener(Object source, ApplicationListener<?> delegate) {
this.source = source;
this.delegate = (delegate instanceof GenericApplicationListener ?
(GenericApplicationListener) delegate : new GenericApplicationListenerAdapter(delegate));
}
//....省略部分代码
@Override
public int getOrder() {
return (this.delegate != null ? this.delegate.getOrder() : Ordered.LOWEST_PRECEDENCE);
}
//过滤之后实际处理事件
protected void onApplicationEventInternal(ApplicationEvent event) {
//...
this.delegate.onApplicationEvent(event);
}
}
SourceFilteringListener
даApplicationListener
Класс декоратора, который фильтрует определенные источники событий. Будет внедрен только прокси-слушатель, соответствующий его событию, а также предусмотрены такие функции, как последовательный запуск прослушивателя.
Часть его будет загружаться при запускеApplicationListener
. После завершения загрузки и инициализации Spring Context (обновление) приложение будет снова обнаружено.ApplicationListener
, и зарегистрируйтесь, в это время мы будем реализовыватьApplicationListener
будет добавлено кSimpleApplicationEventMulticaster
в поддерживаемой коллекции Listener.
Spring также поддерживает мониторинг событий в виде прямых аннотаций.@EventListener(Event.class)
.
выпуск события
ApplicationContext
интерфейс наследуетApplicationEventPublisher
, И вAbstractApplicationContext
Реализуется конкретный код, а фактическое выполнение делегируетсяApplicationEventMulticaster
.
@FunctionalInterface
public interface ApplicationEventPublisher {
//通知所有的注册该事件的应用,事件可以是框架事件如RequestHandledEvent或者特定的应用事件。
default void publishEvent(ApplicationEvent event) {
this.publishEvent((Object)event);
}
void publishEvent(Object var1);
}
Фактическое исполнение делегировано, заинтересованные читатели могут посмотретьAbstractApplicationContext
логика в этой части. Давайте посмотрим на это подробноApplicationEventMulticaster
методы, определенные в интерфейсе.
public interface ApplicationEventMulticaster {
//增加监听者
void addApplicationListener(ApplicationListener<?> listener);
//...
//移除监听者
void removeApplicationListener(ApplicationListener<?> listener);
//...
//广播特定事件给监听者
void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}
AbstractApplicationContext
Он определяет работу и обслуживание прослушивателей, таких как добавление и удаление, и предоставляет методы для широковещательной передачи определенных событий. Давайте посмотрим на конкретный класс реализацииSimpleApplicationEventMulticaster
.ApplicationContext
Автоматический поиск в локальном контейнереApplicationEventMulticaster
реализация, если не будет использоваться значение по умолчаниюSimpleApplicationEventMulticaster
.
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
@Nullable
private Executor taskExecutor;
//...
//用给定的beanFactory创建SimpleApplicationEventMulticaster
public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
setBeanFactory(beanFactory);
}
@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);
}
}
}
//注入给定事件的给定监听器
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
...
}
else {
doInvokeListener(listener, event);
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
//...
}
}
существуетmulticastEvent
В методе, если исполнитель не пустой, видно, что он поддерживает асинхронную публикацию событий. Просто позвоните, когда событие будет опубликованоApplicationContext
серединаpublishEvent
способ публикации события.
Суммировать
В этой статье в основном представлены концепции, связанные с управляемой событиями моделью в Spring. Прежде всего, мы представим модель, управляемую событиями, также известную как шаблон наблюдателя, которая имеет множество применений в нашей повседневной жизни и разработке приложений. После этого в основном вводится механизм событий Spring. Модель Spring, управляемая событиями, состоит из трех частей: события, издатели и подписчики. В сочетании с исходным кодом Spring анализируются определения и реализации этих трех частей. В следующей статье автор объяснит реальный бой в сочетании с конкретными примерами и реализацией в Spring Cloud Config.