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
This commit is contained in:
192
src/main/java/com/chuangzhou/vivid2D/events/EventBus.java
Normal file
192
src/main/java/com/chuangzhou/vivid2D/events/EventBus.java
Normal file
@@ -0,0 +1,192 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user