Files
window-axis-innovators-box1.17/src/main/java/com/chuangzhou/vivid2D/events/EventBus.java
tzdwindows 7 8de6baf653 chore(cache): update jcef cache log files
- 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
2025-11-16 22:43:44 +08:00

192 lines
6.3 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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();
}
}