- Updated Extension Scripts log file entries - Modified shared_proto_db metadata log with new entries - Adjusted Site Characteristics Database log content - Refreshed Session Storage log data
192 lines
6.3 KiB
Java
192 lines
6.3 KiB
Java
package com.chuangzhou.vivid2D.events;
|
||
|
||
import com.axis.innovators.box.events.SubscribeEvent;
|
||
|
||
import java.lang.reflect.Method;
|
||
import java.util.*;
|
||
import java.util.concurrent.ConcurrentHashMap;
|
||
import java.util.concurrent.CopyOnWriteArrayList;
|
||
|
||
/**
|
||
* 事件总线
|
||
*
|
||
* @author tzdwindows 7
|
||
*/
|
||
public class EventBus {
|
||
private static int maxID = 0;
|
||
private final int busID;
|
||
// 使用线程安全的集合以支持并发环境
|
||
private final Map<Class<?>, List<Subscriber>> eventSubscribers = new ConcurrentHashMap<>();
|
||
private final Map<Object, List<Subscriber>> targetSubscribers = new ConcurrentHashMap<>();
|
||
private volatile boolean shutdown;
|
||
|
||
public EventBus() {
|
||
this.busID = maxID++;
|
||
}
|
||
|
||
private static class Subscriber implements Comparable<Subscriber> {
|
||
final Object target;
|
||
final Method method;
|
||
final Class<?> eventType;
|
||
final int priority; // 新增优先级字段
|
||
|
||
Subscriber(Object target, Method method, Class<?> eventType, int priority) {
|
||
this.target = target;
|
||
this.method = method;
|
||
this.eventType = eventType;
|
||
this.priority = priority;
|
||
}
|
||
|
||
@Override
|
||
public int compareTo(Subscriber other) {
|
||
// 按优先级降序排序
|
||
return Integer.compare(other.priority, this.priority);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 注册目标对象的事件监听器
|
||
*
|
||
* @param target 目标对象
|
||
*/
|
||
public void register(Object target) {
|
||
if (targetSubscribers.containsKey(target)) {
|
||
return;
|
||
}
|
||
|
||
List<Subscriber> subs = new CopyOnWriteArrayList<>();
|
||
for (Method method : getAnnotatedMethods(target)) {
|
||
SubscribeEvent annotation = method.getAnnotation(SubscribeEvent.class);
|
||
if (annotation == null) {
|
||
continue;
|
||
}
|
||
|
||
Class<?>[] paramTypes = method.getParameterTypes();
|
||
if (paramTypes.length != 1) {
|
||
System.err.println("Method " + method.getName() + " has @SubscribeEvent annotation but requires " + paramTypes.length + " parameters. Only one is allowed.");
|
||
continue;
|
||
}
|
||
|
||
Class<?> eventType = paramTypes[0];
|
||
// 确保事件参数实现了 Event 接口
|
||
if (!Event.class.isAssignableFrom(eventType)) {
|
||
System.err.println("Method " + method.getName() + " has @SubscribeEvent annotation, but its parameter " + eventType.getName() + " does not implement the Event interface.");
|
||
continue;
|
||
}
|
||
|
||
Subscriber sub = new Subscriber(target, method, eventType, annotation.priority());
|
||
// 使用 computeIfAbsent 简化代码并保证线程安全
|
||
List<Subscriber> eventSubs = eventSubscribers.computeIfAbsent(eventType, k -> new CopyOnWriteArrayList<>());
|
||
eventSubs.add(sub);
|
||
// 每次添加后都进行排序,以保证优先级顺序
|
||
Collections.sort(eventSubs);
|
||
subs.add(sub);
|
||
}
|
||
|
||
if (!subs.isEmpty()) {
|
||
targetSubscribers.put(target, subs);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取目标对象中所有带有 @SubscribeEvent 注解的方法
|
||
*
|
||
* @param target 目标对象
|
||
* @return 方法集合
|
||
*/
|
||
private Set<Method> getAnnotatedMethods(Object target) {
|
||
Set<Method> methods = new HashSet<>();
|
||
Class<?> clazz = target.getClass();
|
||
while (clazz != null) {
|
||
for (Method method : clazz.getDeclaredMethods()) {
|
||
if (method.isAnnotationPresent(SubscribeEvent.class)) {
|
||
methods.add(method);
|
||
}
|
||
}
|
||
clazz = clazz.getSuperclass();
|
||
}
|
||
return methods;
|
||
}
|
||
|
||
/**
|
||
* 注销目标对象的事件监听器
|
||
*
|
||
* @param target 目标对象
|
||
*/
|
||
public void unregister(Object target) {
|
||
List<Subscriber> subs = targetSubscribers.remove(target);
|
||
if (subs == null) {
|
||
return;
|
||
}
|
||
|
||
for (Subscriber sub : subs) {
|
||
List<Subscriber> eventSubs = eventSubscribers.get(sub.eventType);
|
||
if (eventSubs != null) {
|
||
eventSubs.remove(sub);
|
||
if (eventSubs.isEmpty()) {
|
||
eventSubscribers.remove(sub.eventType);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 发布事件
|
||
*
|
||
* @param event 事件对象,必须实现 Event 接口
|
||
* @return 返回一个 PostResult 对象,其中包含事件是否被取消的状态
|
||
*/
|
||
public PostResult post(Event event) {
|
||
if (shutdown) {
|
||
return new PostResult(event.isCancelled(), null);
|
||
}
|
||
|
||
Class<?> eventType = event.getClass();
|
||
List<Subscriber> subs = eventSubscribers.get(eventType);
|
||
|
||
if (subs == null || subs.isEmpty()) {
|
||
return new PostResult(false, null);
|
||
}
|
||
|
||
for (Subscriber sub : subs) {
|
||
try {
|
||
// 无需再创建副本,因为我们使用了 CopyOnWriteArrayList
|
||
sub.method.setAccessible(true);
|
||
sub.method.invoke(sub.target, event);
|
||
|
||
// 如果事件被任何一个订阅者取消,则立即停止分发
|
||
if (event.isCancelled()) {
|
||
break;
|
||
}
|
||
} catch (Exception e) {
|
||
handleException(event, sub, e);
|
||
}
|
||
}
|
||
|
||
// 默认返回一个空的 Map,您可以根据需要进行修改
|
||
Map<String, Boolean> additionalInfo = new HashMap<>();
|
||
return new PostResult(event.isCancelled(), additionalInfo);
|
||
}
|
||
|
||
/**
|
||
* 关闭事件总线,停止处理事件
|
||
*/
|
||
public void shutdown() {
|
||
shutdown = true;
|
||
eventSubscribers.clear();
|
||
targetSubscribers.clear();
|
||
}
|
||
|
||
/**
|
||
* 处理事件处理过程中出现的异常
|
||
*
|
||
* @param event 事件
|
||
* @param subscriber 发生异常的订阅者
|
||
* @param e 异常
|
||
*/
|
||
private void handleException(Event event, Subscriber subscriber, Exception e) {
|
||
System.err.println("Exception thrown by subscriber " + subscriber.target.getClass().getName() +
|
||
"#" + subscriber.method.getName() + " when handling event " + event.getClass().getName());
|
||
e.printStackTrace();
|
||
}
|
||
} |