# 别再面向 for 循环编程了,Spring 观察者模式就很香
# Spring 事件监听机制
在 Spring/ Spring Boot 框架中有一套事件监听机制,可以实现观察者模式
# ApplicationEvent
ApplicationEvent(应用程序事件)它是一个抽象类,相当于观察者模式中的观察目标。
package org.springframework.context;
import java.util.EventObject;
/**
* Class to be extended by all application events. Abstract as it
* doesn't make sense for generic events to be published directly.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
public abstract class ApplicationEvent extends EventObject {
/** use serialVersionUID from Spring 1.2 for interoperability. */
private static final long serialVersionUID = 7099057708183571937L;
/** System time when the event happened. */
private final long timestamp;
/**
* Create a new ApplicationEvent.
* @param source the object on which the event initially occurred (never {@code null})
*/
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
/**
* Return the system time in milliseconds when the event happened.
*/
public final long getTimestamp() {
return this.timestamp;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
ApplicationEvent 继承自 Java 中的 EventObject 事件对象类,Spring 框架中的所有事件都继承自 ApplicationEvent 类,它是所有事件的父类。
ApplicationEvent 主要的核心是类构造器,它可以初始化一个 source 事件关联对象,以便在事件监听器中获取并通知更新。
# ApplicationListener
ApplicationListener(应用程序事件监听器)它是一个接口,相当于观察者模式中的观察者。
package org.springframework.context;
import java.util.EventListener;
/**
* Interface to be implemented by application event listeners.
* Based on the standard {@code java.util.EventListener} interface
* for the Observer design pattern.
*
* <p>As of Spring 3.0, an ApplicationListener can generically declare the event type
* that it is interested in. When registered with a Spring ApplicationContext, events
* will be filtered accordingly, with the listener getting invoked for matching event
* objects only.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @param <E> the specific ApplicationEvent subclass to listen to
* @see org.springframework.context.event.ApplicationEventMulticaster
*/
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
ApplicationListener 继承自 Java 中的 EventListener 事件监听接口,ApplicationListener 类中只有一个 onApplicationEvent 方法,当指定监听的事件被发布后就会被触发执行,可以通过 event 获取事件中的关联对象。
# ApplicationEventPublisher
应用程序事件发布接口,封装了事件发布功能的基础接口。
package org.springframework.context;
/**
* Interface that encapsulates event publication functionality.
* Serves as super-interface for {@link ApplicationContext}.
*
* @author Juergen Hoeller
* @author Stephane Nicoll
* @since 1.1.1
* @see ApplicationContext
* @see ApplicationEventPublisherAware
* @see org.springframework.context.ApplicationEvent
* @see org.springframework.context.event.EventPublicationInterceptor
*/
@FunctionalInterface
public interface ApplicationEventPublisher {
/**
* Notify all <strong>matching</strong> listeners registered with this
* application of an application event. Events may be framework events
* (such as RequestHandledEvent) or application-specific events.
* @param event the event to publish
* @see org.springframework.web.context.support.RequestHandledEvent
*/
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
/**
* Notify all <strong>matching</strong> listeners registered with this
* application of an event.
* <p>If the specified {@code event} is not an {@link ApplicationEvent},
* it is wrapped in a {@link PayloadApplicationEvent}.
* @param event the event to publish
* @since 4.2
* @see PayloadApplicationEvent
*/
void publishEvent(Object event);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
ApplicationEventPublisher 有一个默认接口方法和接口方法,接口方法需要由具体的子类容器实现。
# ApplicationContext
ApplicationContext 这个类就再熟悉不过了,它是 Spring 框架中的核心容器。
ApplicationContext 接口继承了 ApplicationEventPublisher 接口,所以常用的 ApplicationContext 就可以用来发布事件。
# Spring Boot 观察者模式实战
# 新增观察者目标类
package com.chlm.mysession.event;
import org.springframework.context.ApplicationEvent;
/**
* @author : htring
* @packageName : com.chlm.mysession.event
* @description :
* @date : 2021/7/14 16:23
*/
public class MyStackEvent extends ApplicationEvent {
/**
* Create a new ApplicationEvent.
*
* @param source the object on which the event initially occurred (never {@code null})
*/
public MyStackEvent(Object source) {
super(source);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
实现 Spring 框架中的 ApplicationEvent 应用程序事件接口,相当于是一个观察者目标。
# 新增观察者类
package com.chlm.mysession.event;
import cn.hutool.core.util.ObjectUtil;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
/**
* @author : htring
* @packageName : com.chlm.mysession.event
* @description :
* @date : 2021/7/14 16:27
*/
@RequiredArgsConstructor
public class MyStackEventListener implements ApplicationListener<MyStackEvent> {
@NonNull
private String name;
private String article;
/**
* Handle an application event.
*
* @param event the event to respond to
*/
@Async
@Override
public void onApplicationEvent(MyStackEvent event) {
updateArticle(event);
}
private void updateArticle(MyStackEvent event) {
this.article = ObjectUtil.toString(event.getSource());
System.out.printf("我是读者:%s,文章已经更新:%s\n", this.name, this.article);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
实现 Spring 框架中的 ApplicationListener 应用监听接口,相当于是观察者