背景
为了代码解耦,一些与主业务无关的内容最好和主业务分开,我这里写了一个基于事件监听的模型,记录一下。
代码结构
EventBroadcaster 是事件发布器,
ModelEvent继承自java.util.EventObject代表一个具体的事件
EventListener是监听器的接口
ModelEventListener和ModelEventListener2为监听ModelEvent的2个监听器,监听器之间的顺序可以使用spring的@Order注解或者java的@javax.annotation.Priority来控制
具体代码
package com.siiirius.event;
import java.util.EventObject;
/**
* 顶层监听器接口
* Created by siiiriu on 2020/7/6.
*/
public interface EventListener<E extends EventObject> extends java.util.EventListener {
/**
* process method
*
* @param event
*/
void process(E event);
}
package com.siiirius.model;
import java.io.Serializable;
/**
* 一个具体数据模型
* Created by siiiriu on 2020/7/6.
*/
public class Model implements Serializable{
private static final long serialVersionUID = 42L;
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Model{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
package com.siiirius.event;
import com.siiirius.model.Model;
import java.util.EventObject;
/**
* Model模型产生的事件
* Created by siiiriu on 2020/7/6.
*/
public class ModelEvent extends EventObject {
private static final long serialVersionUID = 42L;
public ModelEvent(Model model) {
super(model);
}
@Override
public Model getSource() {
return (Model)super.getSource();
}
}
package com.siiirius.event;
import org.springframework.stereotype.Component;
/**
* 一个model事件的监听器
* Created by siiiriu on 2020/7/6.
*/
@Component
public class ModelEventListener implements EventListener<ModelEvent> {
@Override
public void process(ModelEvent event) {
System.out.println("process 1." + event.getSource());
}
}
package com.siiirius.event;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 另外一个Model事件的监听器,希望比ModelEventListener要早执行
* Created by siiiriu on 2020/7/6.
*/
@Component
@Order(0)
public class ModelEventListener2 implements EventListener<ModelEvent> {
@Override
public void process(ModelEvent event) {
System.out.println("process 2." + event.getSource());
}
}
package com.siiirius.event;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import java.lang.reflect.ParameterizedType;
import java.util.*;
/**
* 事件发布器,使用静态方法EventBroadcaster.broadcastEvent(..)发布一个事件
* Created by siiiriu on 2020/7/6.
*/
@Component
public class EventBroadcaster {
private static EventBroadcaster instance;
Map<Class<? extends EventObject>, List<EventListener<? extends EventObject>>> map = new HashMap<>();
@Autowired
private List<EventListener<? extends EventObject>> listeners;
@PostConstruct
public void init() {
instance = this;
if (CollectionUtils.isEmpty(listeners)) {
return;
}
for (EventListener<? extends EventObject> listener : listeners) {
Class<? extends EventObject> c = getListenEventClass(listener);
map.computeIfAbsent(c, key -> new ArrayList<>()).add(listener);
}
// 排序,使用Spring的排序
for (List<EventListener<? extends EventObject>> eventListeners : map.values()) {
eventListeners.sort(AnnotationAwareOrderComparator.INSTANCE);
}
}
// 获取泛型
private Class<? extends EventObject> getListenEventClass(EventListener<? extends EventObject> listener) {
ParameterizedType type = (ParameterizedType)listener.getClass().getGenericInterfaces()[0];
return (Class<? extends EventObject>) type.getActualTypeArguments()[0];
}
/**
* 发布事件
*
* @param event
*/
public static void broadcastEvent(EventObject event) {
instance.broadcast(event);
}
private void broadcast(EventObject eventObject) {
List<EventListener<? extends EventObject>> eventListeners = map.get(eventObject.getClass());
if (eventListeners == null) {
//log
return;
}
for (EventListener<? extends EventObject> eventListener : eventListeners) {
EventListener<EventObject> listener = (EventListener<EventObject>) eventListener;
listener.process(eventObject);
}
}
}
然后我们来一个测试类
import com.siiirius.event.EventBroadcaster;
import com.siiirius.event.ModelEvent;
import com.siiirius.event.ModelEventListener;
import com.siiirius.event.ModelEventListener2;
import com.siiirius.model.Model;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Created by siiiriu on 2020/7/6.
*/
@ContextConfiguration(
classes = {
EventBroadcaster.class,
ModelEventListener.class,
ModelEventListener2.class
}
)
@RunWith(SpringRunner.class)
public class EventBroadcasterTest {
@Test
public void test() {
Model model = new Model();
model.setId(1L);
model.setName("name");
EventBroadcaster.broadcastEvent(new ModelEvent(model));
}
}
执行结果
process 2.Model{id=1, name='name'}
process 1.Model{id=1, name='name'}
框架已经搭好了,后面只需要增加Event以及对应的Listener,然后在需要发布事件的位置使用EventBroadcaster.broadcastEvent(…)就可以发布并且消费事件了。
后续,可以考虑增加线程池异步执行任务