原理:觀察者模式
spring的事件監聽有三個部分組成,事件(ApplicationEvent)、監聽器(ApplicationListener)和事件發布操作。
事件
事件類需要繼承ApplicationEvent,代碼如下:
public class HelloEvent extends ApplicationEvent { private String name; public HelloEvent(Object source, String name) { super(source); this.name = name; } public String getName() { return name; } }
這里為了簡單測試,所以寫的很簡單。
事件類是一種很簡單的pojo,除了需要繼承ApplicationEvent也沒什么了,這個類有一個構造方法需要super。
事件監聽器
@Component public class HelloEventListener implements ApplicationListener<HelloEvent> { private static final Logger logger = LoggerFactory.getLogger(HelloEventListener.class); @Override public void onApplicationEvent(HelloEvent event) { logger.info("receive {} say hello!",event.getName()); } }
事件監聽器需要實現ApplicationListener接口,這是個泛型接口,泛型類類型就是事件類型,其次需要是spring容器托管的bean,所以這里加了@component,只有一個方法,就是onApplicationEvent。
事件發布操作
有了事件和監聽器,不發布事件也不用,事件發布方式很簡單
applicationContext.publishEvent(new HelloEvent(this,"lgb"));
然后調用方法就能看到
2018-10-02 19:08:00.052 INFO 284928 --- [nio-5577-exec-3] l.b.e.c.s.event.HelloEventListener : receive lgb say hello!
疑問
- 同樣的事件能有多個監聽器 -- 經過測試是可以的
- 事件監聽器一定要寫一個類去實現嗎 -- 其實是可以不需要的,spring有個注解@EventListener,修飾在方法上,稍后給出使用方法
- 事件監聽操作和發布事件的操作是同步的嗎? -- 是的,所以如果有事務,監聽操作也在事務內
使用@EventListener注解
先給出代碼
@EventListener public void listenHello(HelloEvent event) { logger.info("listen {} say hello from listenHello method!!!",event.getName()); }
EventListener這個注解其實可以接受參數來表示事件源的,有兩個參數classes和condition,顧明思議前者是表示哪一個事件類,后者是當滿足什么條件是會調用該方法,但其實都可以不用用到,直接在方法上寫參數HelloEvent就行