本人Git地址:https://github.com/a422478514/java-practice/tree/master/src/main/java/com/daquan/_202007/_01/spring/event
一、監聽器模式
監聽者通過向發佈者註冊自身(自身可以理解爲監聽者對象),如果有事件發生,發佈者會調用註冊列表裏的監聽者的某方法並把事件(事件內部持有事件源)作爲參數傳入。
在Spring中需要我們自己定義事件監聽器、事件。發佈器不需要自定義,但需要設法通過上下文拿到發佈器。(可以思考下爲什麼這麼設計?)
二、基於Spring實現的消息監聽類圖詳解
1、事件:
EventObject:是JDK自帶的事件,是個具體的類,本身持有一個Object事件源用來定義本次事件的具體描述。EventObject本身是事件源的容器。
ApplicationEvent:是對EventObject的簡單封裝(擴展),但是是個抽象類,用來作爲自定義事件類的基類,這樣設計也是爲了滿足對監聽器對具體某自定義事件的監聽。該類構造函數裏調用了super(source)用來封裝事件源,並提供了一個返回當前時間的方法。
MySpringApplicationEvent:是自定義的事件類,也是本次講解中要被監聽的事件。其構造函數需要的參數同樣是自定義的事件源。
2、發佈者容器:
Aware是個空接口,用來方便擴展,也是Spring的慣用操作
ApplicationEventPublisherAware是Spring中用來識別注入ApplicationEventPublisher對象的特殊接口。(一般xxxxxAware都是用來給實現類注入xxxxx的)
MySpringEventPublisherContext是自定義的發佈者容器,裏面封裝了Spring提供的事件發佈器
3、監聽者
EventListener:Spring提供的空接口
ApplicationListener:繼承了EventListener且通過使用泛型來實現針對某一具體事件類型的監聽,onApplicationEvent作爲事件觸發時調用的函數。
4、自定義事件源
MyEventSource是事件源的具體實現,是事件的核心內容,該類持有大部分有效信息。
三、代碼
1、MyEventSource.java
/**
* 用來描述事件源的實體類
*/
public class MyEventSource implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
public MyEventSource(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "MyEventSource{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
2、MySpringApplicationEvent.java
import org.springframework.context.ApplicationEvent;
/**
* 使用spring事件框架自定義的事件
*/
public class MySpringApplicationEvent extends ApplicationEvent {
public MySpringApplicationEvent(MyEventSource eventSource) {
super(eventSource);
}
}
3、MySpringApplicationListener.java
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Service;
/**
* 基於Spring事件框架自定義的事件監聽器,注意泛型用來確定要監聽的事件
*/
@Service
public class MySpringApplicationListener implements ApplicationListener<MySpringApplicationEvent> {
@Override
public void onApplicationEvent(MySpringApplicationEvent mySpringApplicationEvent) {
System.out.println("監聽到事件:"+mySpringApplicationEvent.getSource().toString());
}
}
4、MySpringEventPublisherContext.java
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
/**
* 事件發佈器上下文
*/
@Service
public class MySpringEventPublisherContext implements ApplicationEventPublisherAware {
private ApplicationEventPublisher applicationEventPublisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
System.out.println("注入事件發佈器");
this.applicationEventPublisher = applicationEventPublisher;
}
public ApplicationEventPublisher getApplicationEventPublisher() {
return applicationEventPublisher;
}
}
5、TestSpringEventMain.java
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 測試SpringEvent的啓動器
*/
public class TestSpringEventMain {
public static void main(String[] args) {
System.out.println("1、加載spring容器");
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("application.xml");
System.out.println("2、從容器中獲取事件發佈器");
MySpringEventPublisherContext publisherContext = classPathXmlApplicationContext.getBean(MySpringEventPublisherContext.class);
System.out.println("3、發佈事件");
publisherContext.getApplicationEventPublisher().publishEvent(new MySpringApplicationEvent(new MyEventSource(1,"daquan")));
}
}
6、配置文件 application.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-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<context:annotation-config />
<!--自動掃描含有@Service將其注入爲bean -->
<context:component-scan base-package="com.daquan._202007" />
</beans>
運行5、結果如下: