Синопсис
События в спринге реализуются очень просто. Любой бин может прослушивать события если он реализует интерфейс ApplicationListener. Само событие это класс производный от ApplicationEvent а сам этот класс не обязан быть бином. Публикуются события с помощью метода publishEvent() класса реализующего интерфейс ApplicationEventPublisher который наследует интерфейс ApplicationContext.
Готовый проект можно взять с gitHub: https://github.com/dev-blogs/spring подпроект event-handler
Структура и описание проекта
Создадим проект в котором поднимается спринговый контекст и по факту поднятия спринг тригнет класс StartEventHandler через событие ContextRefreshedEvent. Класс StartEventHandler является в свою очередь бином в который спринг инжектит кастомный объект класса Publisher через который, в свою очередь, будет производиться рассылка сообщений типа MessageEvent через спринговый класс ApplicationContext (который в него кладется через листенер ApplicationContextAware когда поднимается бин Publisher) по остальным бинам слушателям в нашем случае это бин MessageEventListener.
То есть когда поднимается контекст спринга он сообщает об этом бину StartEventHandler, бин StartEventHandler через заинжектинный в него бин Publisher тригает его метод publish(), бин Publisher рассылает сообщения всем слушателям через спринговый бин ApplicationContext.
event-handler ├──src │ ├─main │ │ └─java │ │ └─com │ │ └─devblogs │ │ └─event │ │ ├─App.java │ │ ├─MessageEvent.java │ │ ├─MessageEventListener.java │ │ ├─Publisher.java │ │ └─StartEventHandler.java │ └─resources │ └─context.xml └──pom.xml
Класс события
MessageEvent — класс события:
MessageEvent.java
package com.devblogs.event; import org.springframework.context.ApplicationEvent; public class MessageEvent extends ApplicationEvent { private String msg; public MessageEvent(Object source, String msg) { super(source); this.msg = msg; } public String getMessage() { return msg; } }
Класс слушатель
MessageEventListener — класс слушатель. Классом слушателем может стать любой класс который:
А) является бином
Б) реализует интерфейс ApplicationListener
Когда выполняются два этих условия, ApplicationContext автоматически регистрирует его как бин-слушатель. В нашем примере, класс MessageEventListener заинтересован только в событиях MessageEvent так как он реализует типизированный интерфейс ApplicationListener:
MessageEventListener.java
package com.devblogs.event; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Service; @Service public class MessageEventListener implements ApplicationListener<MessageEvent> { public void onApplicationEvent(MessageEvent event) { MessageEvent msgEvt = (MessageEvent) event; System.out.println("Received: " + msgEvt.getMessage()); } }
Публикация события
Для того чтобы опубликовать событие, нужно создать экземпляр класса события и передать его методу publishEvent класса реализующего интерфейс ApplicationEventPublisher которым является класс ApplicationContext:
Publisher.java
package com.devblogs.event; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Service; @Service public class Publisher implements ApplicationContextAware { private ApplicationContext context; public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = applicationContext; } public void publish(String message) { context.publishEvent(new MessageEvent(this, message)); } }
Класс StartEventHandler является слушателем события ContextRefreshedEvent которое публикуется самим спрингом после того как контекст спринга был сформирован. В этот класс инжектится объект Publisher который был определён выше, после того как слушатель словит события о том, что спринг сконфигурирован и готов к работе, класс StartEventHandler, в свою очередь, публикует два события MessageEvent с сообщениями test message1 и test message2:
StartEventHandler.java
package com.devblogs.event; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.stereotype.Service; @Service public class StartEventHandler implements ApplicationListener<ContextRefreshedEvent> { @Autowired private Publisher publisher; public void onApplicationEvent(ContextRefreshedEvent event) { System.out.println("StartEventHandler listener"); publisher.publish("test message1"); publisher.publish("test message2"); } }
Класс энтерпоинт или класс запуска приложения:
App.java
package com.devblogs.event; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main(String[] args) { new ClassPathXmlApplicationContext("classpath:context.xml"); } }
Конфигурация
context.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> <context:component-scan base-package="com.devblogs.event"/> </beans>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.devblogs</groupId> <artifactId>event-handler</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>event-handler</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>3.2.7.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> </project>
Сборка и запуск
Для запуска примера запустим на выполнение файл com.devblogs.event.App или соберем проект в джарник и запустим джарник (как это делается описывается в этом посте:
StartEventHandler listener Received: test message1 Received: test message2
Классные статьи, читаются на ура) Спасибо.