相关Spring接口
org.springframework.context.ApplicationEvent
org.springframework.context.support.AbstractApplicationContext
org.springframework.context.ApplicationListener
概述
订阅者模式在spring中的使用
技术细节
监听者ApplicationListener
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
调用链:
AbstractApplicationContext
:: publishEvent
SimpleApplicationEventMulticaster
:: multicastEvent
:: invokeListener
:: doInvokeListener
ApplicationListener
:: onApplicationEvent
事件ApplicationEvent
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;
}
}
查看调用的父类方法为:
public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");
this.source = source;
}
可以看到会记录在event对象的source属性中,而定义为:
protected transient Object source;
其中transient表示属性不需要关键字
实践
需求:
中间件处理原始请求时,无法直接同步返回结果(第三方没有相关业务api提供调用), 这时候需要先返回一个同步结果,再进行异步操作.
可以开一个线程来做,也可以用spring框架中的生产订阅模式.
设计:
三个类:
1.事件 :
Event.class
2.生产者
Publisher.class
3.监听者(消费者,订阅者)
ListenerA.class
ListenerB.class
…
流程: 定义一个事件,生产者将它上线,触发消费者的消费操作
代码:
定义一些类
data class Message(
val id: String?
)
class Event(message: Message) : ApplicationEvent(message)
@Service
class Publisher(val applicationContext: AbstractApplicationContext) {
fun publish(event: Event) {
applicationContext.publishEvent(event)
}
}
@Service
class ListenerA : ApplicationListener<Event> {
override fun onApplicationEvent(event: Event) {
val message = event.source as Message
println("A get $message")
}
}
@Service
class ListenerB : ApplicationListener<Event> {
override fun onApplicationEvent(event: Event) {
val message = event.source as Message
println("B get $message")
}
}
@Service
class ListenerC : ApplicationListener<Event> {
override fun onApplicationEvent(event: Event) {
val message = event.source as Message
println("C get $message")
}
}
主程序
@Autowired
lateinit var publisher: Publisher
@Test
fun eventTest(){
val event = Event(Message("01"))
publisher.publish(event)
}
控制台输出
A get Message(id=01)
B get Message(id=01)
C get Message(id=01)
完美!
(补充)更优雅的写法
class myTest{
@Autowired
lateinit var publisher: Publisher
@Test
fun eventTest(){
val event = Event(Message("01"))
publisher.publish(event)
}
}
data class Message(
val id: String?
)
class Event(val message: Message)
@Service
class Publisher(val applicationContext: AbstractApplicationContext) {
fun publish(event: Event) {
applicationContext.publishEvent(event)
}
}
@Service
class ListenerA {
@Async
@EventListener
fun onApplicationEvent(event: Event) {
val message = event.message
println("A get $message")
}
@Async
@EventListener
fun onApplicationEventB(event: Event) {
val message = event.message
println("B get $message")
}
}
注意: 监听者需要注册成 service, 这样才能被spring 识别起来.
思考:
private val publisher: ApplicationEventPublisher 的publisher.publishEvent(event) vs appliationContext.pushEvent(event)