关键要素:事件,事件发布器,事件监听器
发布器 Subject
public class Subject {
private List<Observer> observers = new ArrayList<>();
public void attach(Observer observer) {
this.observers.add(observer);
}
public void notifyAllObserver(){
for (Observer observer : observers) {
observer.update();
}
}
}
事件抽象类 Observer
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
事件实现类 OrderOberser
public class OrderObserver extends Observer{
public OrderObserver(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("orderObserver update");
}
}
通知事件
public class MainClazz {
public static void main(String[] args) {
Subject subject = new Subject();
new OrderObserver(subject);
subject.notifyAllObserver();
}
}
可以通过观察者模式实现领域事件
事件抽象
public abstract class DomainEvent {
public abstract Date createDate();
public abstract String content();
}
事件监听接口
public interface DomainEventListener<T extends DomainEvent> {
void handler(T event);
}
事件发布器
public class DomainEventPublisher {
private static ConcurrentHashMap<Class<? extends DomainEvent>, List<DomainEventListener<? extends DomainEvent>>> listenerMap = new ConcurrentHashMap<>();
public synchronized static <T extends DomainEvent> void register(Class<T> clazz, DomainEventListener<T> listener) {
List<DomainEventListener<? extends DomainEvent>> listenerList = listenerMap.get(clazz);
if (listenerList == null) {
listenerList = new ArrayList<>();
}
listenerList.add(listener);
listenerMap.put(clazz, listenerList);
}
public static <T extends DomainEvent> void publish(T event) {
List<DomainEventListener<? extends DomainEvent>> listenerList = listenerMap.get(event.getClass());
if (listenerList != null) {
for (DomainEventListener listener : listenerList) {
listener.handler(event);
}
}
}
}
事件实现
public class TestEvent extends DomainEvent{
private String flowNo;
@Override
public Date createDate() {
return new Date();
}
@Override
public String content() {
return "事件内容";
}
public void getFlowNo(){
System.out.println("该事件自己的事件逻辑");
}
}
监听器实现
public class TestListener implements DomainEventListener<TestEvent>{
public TestListener() {
DomainEventPublisher.register(TestEvent.class, this);
}
@Override
public void handler(TestEvent event) {
event.getFlowNo();
String content = event.content();
System.out.println("content = " + content);
}
}
调用
public class MainClazz {
public static void main(String[] args) {
TestListener testListener = new TestListener();
DomainEventPublisher.publish(new TestEvent());
}
}
如果想要异步执行事件,可以在事件发布器中定义一个线程池,使用线程池执行事件的处理
public class DomainEventPublisher {
private static Executor executor = new ThreadPoolExecutor(10, 10, 0, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
private static ConcurrentHashMap<Class<? extends DomainEvent>, List<DomainEventListener<? extends DomainEvent>>> listenerMap = new ConcurrentHashMap<>();
public synchronized static <T extends DomainEvent> void register(Class<T> clazz, DomainEventListener<T> listener) {
List<DomainEventListener<? extends DomainEvent>> listenerList = listenerMap.get(clazz);
if (listenerList == null) {
listenerList = new ArrayList<>();
}
listenerList.add(listener);
listenerMap.put(clazz, listenerList);
}
public static <T extends DomainEvent> void publish(T event) {
List<DomainEventListener<? extends DomainEvent>> listenerList = listenerMap.get(event.getClass());
if (listenerList != null) {
for (DomainEventListener listener : listenerList) {
executor.execute(()->{
listener.handler(event);
});
}
}
}
}
谷歌的eventbus也是一种观察者模式,可以用来实现相同的功能
事件发布器
@Component
public class GuavaPublisher {
private EventBus eventBus = new EventBus("test");
@Autowired
private TestListener testListener;
@PostConstruct
public void init(){
eventBus.register(testListener);
}
public void postEvent(){
eventBus.post(new TestEvent());
}
}
监听器
监听器需要在一个方法上使用 @Subscribe 注解
@Component
public class TestListener {
@Subscribe
public void handler(TestEvent event){
String content = event.getContent();
System.out.println("content = " + content);
}
}
事件类
public class TestEvent {
private String content;
public String getContent(){
return "content";
}
}
如果想要使用异步,可以使用 AsyncEventBus
private AsyncEventBus eventBus = new AsyncEventBus(new ThreadPoolExecutor(10, 10, 0, TimeUnit.SECONDS, new LinkedBlockingDeque<>()));