В сложной среде разработки программного обеспечения особенно важны связь и обмен информацией между компонентами. Платформа Spring, как одна из самых популярных платформ разработки в мире Java, предоставляет мощную модель прослушивателя событий, которая делает связь между компонентами более гибкой и несвязанной. В этой статье в основном обсуждаются принципы, методы использования и применение прослушивателей событий Spring в реальной разработке, в надежде предоставить разработчикам практический справочник.
Слушатели событий Spring — это механизм обработки событий в приложениях Spring. События обычно представляют собой изменения в состоянии приложения, и прослушиватели несут ответственность за реакцию на эти изменения. С помощью прослушивателя событий Spring разработчики могут реализовать обмен информацией между различными компонентами на основе разделения, улучшая удобство сопровождения и масштабируемость кода.
Целью этой статьи является глубокое изучение основных принципов прослушивателей событий Spring, руководство читателями по использованию прослушивателей в реальной разработке и демонстрация сценариев использования и методов реализации прослушивателей на некоторых конкретных примерах. Мы также подробно проанализируем исходный код прослушивателя Spring, надеясь, что читатели смогут глубже понять принцип его работы. Я надеюсь, что благодаря этой статье читатели смогут более опытно использовать прослушиватели событий Spring для создания гибких и удобных в обслуживании приложений.
Все следующие примеры загружены на Github. Вы можете загрузить проект локально и запустить его.
Пример Github (если вы еще не знакомы с Gradle),Рекомендуется прочитать мои предыдущие статьи.):gradle-spring-boot-demo
Понимание принципов работы прослушивателей событий Spring является обязательным условием для эффективного использования этого механизма. В этой главе подробно рассматриваются основные компоненты прослушивателей событий Spring и то, как они работают вместе.
В модели прослушивателя событий Spring в основном используются три основных компонента: событие (Event), прослушиватель (Listener) и издатель событий (Event Publisher).
События обычно инициируются определенным действием или изменением состояния. Весной, с момента Определить событие Обычно требуется наследованиеApplicationEvent
добрый。событиедобрый包含了событиеиз基本информация,Например источник события, время их возникновения и т. д.
import org.springframework.context.ApplicationEvent;
public class CustomEvent extends ApplicationEvent {
public CustomEvent(Object source) {
super(source);
}
}
Слушатель несет ответственность за получение иобрабатывать события。Весной,Слушатели обычно реализуютсяApplicationListener
интерфейсиздобрый,Необходимо определитьonApplicationEvent
метод, чтобы быть конкретнымобрабатывать события。
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class CustomEventListener implements ApplicationListener<CustomEvent> {
@Override
public void onApplicationEvent(CustomEvent event) {
// обрабатывать события
System.out.println("Received custom event - " + event);
}
}
Роль издателя событий — уведомлять всех зарегистрированных слушателей о событиях. Весеннее приложение,ApplicationEventPublisher
Интерфейс отвечает за Публикация событий。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
@Component
public class CustomEventPublisher {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
public void doSomethingAndPublishAnEvent(final String message) {
System.out.println("Publishing custom event.");
CustomEvent customEvent = new CustomEvent(message);
applicationEventPublisher.publishEvent(customEvent);
}
}
Основной рабочий процесс модели прослушивателя событий выглядит следующим образом:
Освоив основные принципы и компоненты прослушивателей событий Spring, мы продолжим изучать, как их использовать в реальной разработке. Определяя события, создавая прослушиватели и публикуя события, мы можем передавать информацию между различными компонентами.
Весной,Мы можем наследоватьApplicationEvent
добрый Приходить定义自己изсобытие。这个добрый需要包含所有与событие相关изинформация。
public class TestEvent extends ApplicationEvent {
private String message;
public TestEvent(Object source, String message) {
super(source);
this.message = message;
}
public String getMessage() {
return message;
}
}
В этом примере,Мы создали файл под названиемTestEvent
изсобытиедобрый,该добрый中含有一个字符串добрый型изmessage
Поле,Используется для передачи информации, связанной с событием.
После того, как событие определено, нам нужно Создать прослушивательобработать это событие。Слушатель реализованApplicationListener
интерфейсиздобрый,Нужно перезаписатьonApplicationEvent
метод Определить Логика обработки события.
@Component
public class TestEventListener implements ApplicationListener<TestEvent> {
@Override
public void onApplicationEvent(TestEvent testEvent) {
// [3] Здесь вы можете выполнить логику после прослушивания события, Слушайте источник события, запускайте действие!
System.out.println("Прослушивал TestEvent:" + testEvent.getMessage());
}
}
В этом примере,Мы определяем слушателяTestEventListener
,Этот слушатель распечатает полученноеTestEvent
в случаеmessage
информация。
Наконец, нам нужно опубликовать событие。Публикация событийобычно состоит изиздатель событийApplicationEventPublisher
завершить。
@Component
public class TestEventPublisher {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
public void publish(String message) {
// [2]использоватьpublishEventметодопубликовать событие,источник событийдляTestEvent applicationEventPublisher.publishEvent(new TestEvent(this, message));
}
}
В этом примере,TestEventPublisher
добрый中изpublishEvent
метод会创建并发布一个新изTestEvent
событие。
С помощью этих трех шагов мы можем реализовать определение событий, мониторинг и публикацию в приложениях Spring. Это не только помогает разделить компоненты, но также повышает удобство сопровождения и масштабируемость кода.
@SpringBootTest
class GradleSpringBootDemoApplicationTests {
@Autowired
private TestEventPublisher testEventPublisher;
@Test
void contextLoads() {
// [1] опубликовать событие
testEventPublisher.publish("Hello, Spring!");
}
}
Выполнение завершено, и результаты следующие:
Чтобы глубже понять шаблон прослушивателя Spring, давайте напишем простой пример на основе шаблона проектирования прослушивателя, шаг за шагом показав, как создавать события, прослушиватели и как публиковать события.
Мы создадим простую систему регистрации пользователей. После успешной регистрации пользователя система опубликует событие регистрации, и соответствующий прослушиватель прослушает это событие, а затем выполнит соответствующие операции, такие как отправка приветственного письма и запись журналов.
Сначала мы определяем событие, когда регистрация пользователя успешна. Это событие содержит основную информацию о пользователе.
public class UserRegisterEvent {
private final String username;
private final String email;
public UserRegisterEvent(String username, String email) {
this.username = username;
this.email = email;
}
// Getters
}
Далее мы создаем два слушателя: один отвечает за отправку приветственного письма, а другой — за запись журнала регистрации пользователей.
public class WelcomeEmailListener {
public void sendWelcomeEmail(UserRegisterEvent event) {
System.out.println("Sending welcome email to " + event.getEmail());
}
}
public class UserRegisterLogListener {
public void logUserRegister(UserRegisterEvent event) {
System.out.println("Logging user register: " + event.getUsername());
}
}
Наконец, мы создаем службу регистрации пользователей, которая публикует события после успешной регистрации пользователя.
import java.util.ArrayList;
import java.util.List;
public class UserRegisterService {
private final List<Object> listeners = new ArrayList<>();
public void registerUser(String username, String email) {
// Логика регистрации пользователя (опущена)
System.out.println("User registered: " + username);
// опубликовать событие
UserRegisterEvent event = new UserRegisterEvent(username, email);
for (Object listener : listeners) {
if (listener instanceof WelcomeEmailListener) {
((WelcomeEmailListener) listener).sendWelcomeEmail(event);
} else if (listener instanceof UserRegisterLogListener) {
((UserRegisterLogListener) listener).logUserRegister(event);
}
}
}
public void addListener(Object listener) {
listeners.add(listener);
}
}
мы можем добавитьmain
метод模拟用户из注册过程并触发Публикация событийи контролировать。
public class Runner {
public static void main(String[] args) {
// Создать экземпляр UserRegisterService.
UserRegisterService userRegisterService = new UserRegisterService();
// Добавьте прослушиватель в UserRegisterService.
userRegisterService.addListener(new WelcomeEmailListener());
userRegisterService.addListener(new UserRegisterLogListener());
// Имитация регистрации пользователя
userRegisterService.registerUser("JohnDoe", "john.doe@example.com");
}
}
Когда вы запустите этоmain
метод时,UserRegisterService
Логика регистрации будет выполнена,Опубликовано позжеUserRegisterEvent
событие,иWelcomeEmailListener
иUserRegisterLogListener
监听器将会捕获到这个событие并执行相应из操作。
Результаты бега следующие:
User registered: kfaino
Sending welcome email to kfaino@example.com
Logging user register: kfaino
В этой главе мы рассмотрим детали реализации прослушивателей Spring, чтобы глубже понять, как Spring проектирует и реализует прослушиватели событий.
ApplicationEvent
иApplicationListener
даSpringМеханизм прослушивания событийкраеугольный камень。
ApplicationEvent
да所有Springсобытиеиз基добрый,он наследует отjava.util.EventObject
。он содержитисточник события и временную метку события.
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
public final long getTimestamp() {
return this.timestamp;
}
}
ApplicationListener
да一个泛型интерфейс,используется для处理特定добрый型изсобытие。它包含一个методonApplicationEvent
,用户需要实现该метод Определить логика обработки событий.
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
ApplicationEventPublisher
дасобытие发布из核心интерфейс。он определяетpublishEvent
метод,используется дляопубликовать событие для всех подходящих слушателей.
public interface ApplicationEventPublisher {
void publishEvent(ApplicationEvent event);
void publishEvent(Object event);
}
ApplicationContext
унаследованныйApplicationEventPublisher
интерфейс,Итак, в контейнере Spring,可以直接использоватьApplicationContext
Приходитьопубликовать событие。
Весной,распространение событийда通过SimpleApplicationEventMulticaster
добрый Приходить实现из。这个добрый有一个multicastEvent
метод,Он доставит событие всем соответствующим прослушивателям.
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
for (final ApplicationListener<?> listener : getApplicationListeners(event, eventType)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
} else {
invokeListener(listener, event);
}
}
}
}
В этом методе,getApplicationListeners
используется для获取所有匹配из监听器,ЗатемinvokeListener
метод被用Приходить触发这些监听器。
Путем углубленного анализа исходного кода прослушивателей событий Spring мы можем более четко понять, как Spring реализует определение, публикацию и обработку событий, что помогает нам более эффективно использовать этот механизм в реальной разработке.
Сама среда Spring предоставляет некоторые встроенные события, которые представляют некоторые этапы жизненного цикла или определенные операции контейнера, которые могут помочь нам лучше отслеживать приложения и управлять ими.
ContextRefreshedEvent
событие在SpringЗапускается, когда контейнер инициализируется или обновляется,То есть, когда все bean-компоненты были успешно загружены и был вызван постпроцессор.,и после того, как все одноэлементные bean-компоненты были предварительно созданы.
@EventListener
public void handleContextRefresh(ContextRefreshedEvent event) {
System.out.println("Context Refreshed: " + event.getTimestamp());
}
В SpringBoot мы можем написать следующий код:
@Component
public class MyServletContextListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
// TODO Здесь вы можете выполнить некоторые операции инициализации, такие как запрос к базе данных, кэширование данных, загрузка конфигурации и т. д.
System.out.println("Триггер завершения загрузки контейнера Spring");
}
}
Обратный вызов после того, как Spring завершит инициализацию:
Когда контейнер Spring закрыт,ContextClosedEvent
событие会被触发。на этом этапе,Все одноэлементные компоненты были уничтожены.
@EventListener
public void handleContextClose(ContextClosedEvent event) {
System.out.println("Context Closed: " + event.getTimestamp());
}
当использоватьConfigurableApplicationContext
изstart()
метод启动Springконтекст,вызоветContextStartedEvent
событие。
@EventListener
public void handleContextStart(ContextStartedEvent event) {
System.out.println("Context Started: " + event.getTimestamp());
}
Соответственно,当использоватьConfigurableApplicationContext
изstop()
метод停止Springконтекст,вызоветContextStoppedEvent
событие。
@EventListener
public void handleContextStop(ContextStoppedEvent event) {
System.out.println("Context Stopped: " + event.getTimestamp());
}
ApplicationReadyEvent
событие在SpringЗапускается, когда приложение завершило работу и готово принимать запросы.。
@EventListener
public void handleApplicationReady(ApplicationReadyEvent event) {
System.out.println("Application Ready: " + event.getTimestamp());
}
Помимо вышеперечисленных событий,Spring также предоставляет ряд других встроенных событий.,нравитьсяRequestHandledEvent
、ServletRequestHandledEvent
ждать,Это может помочь нам более полно понимать и управлять рабочим статусом приложения.
Понимание и использование встроенных событий Spring может помочь нам более удобно и быстро отслеживать жизненный цикл и состояние работы приложения, а также оптимизировать производительность и стабильность приложения. В то же время это также дает нам удобные средства для мониторинга этих событий и выполнения индивидуальной логики для удовлетворения различных потребностей бизнеса.
В этой главе мы подробно рассмотрим прослушиватели Spring. Узнайте об этих преимуществах и Недостатки помогут нам принимать более разумные решения о том, когда и что. использовать прослушиватели Spring。
🌟 предположение: 在考虑использоватьSpringслушатель,Удобство, которое оно приносит, следует сопоставлять с возможным недостатком. В сложных бизнес-сценариях, где действительно необходимо использовать события для разделения модулей.,Spring Listener — очень подходящий выбор. но,В простых сценариях, не требующих развязки,Следует рассмотреть вопрос о том, чтобы избежать использования прослушивателей.,чтобы уменьшить ненужную сложность и накладные расходы на производительность.
В реальном развитии,Крайне важно, как использовать прослушиватели Spring более разумно и эффективно. Вот несколько советов по использованию слушателей Spring.,Это может помочь вам более разумно и гибко применять прослушиватели Spring.
@Async
@EventListener
public void handleAsyncEvent(MyEvent event) {
// обрабатывать события
}
В этой статье мы углубимся в принципы работы слушателей Spring. Фильм, на основе аудиошаблона Фильм. Реальные кейсы проектирования, Встроенные события Spring, Анализ исходного кода、Преимущества и недостаткиа такжелучшие практика. Ниже мы проведем краткий обзор и Подвести итог。
В ходе обучения мы узнали: