claude

我仔细审查了你的事件系统实现,发现了一些问题和可以优化的地方:

🔴 严重问题

1. 泛型类型擦除导致监听器混乱

inline fun <reified T : AppEvent> on(noinline handler: (T) -> Unit): EventListener<T> {
    return on(T::class.java, Consumer(handler))
}

fun <T : AppEvent> on(clazz: Class<T>, handler: Consumer<T>): EventListener<T> {
    val listener = EventListener(handler)
    listeners.computeIfAbsent(clazz) { CopyOnWriteArrayList() }.add(listener)
    return listener
}

问题: 当你监听父类事件时,子类事件不会触发监听器。

// 这个监听器永远不会被触发!
eventBus.on<AppEvent> { event ->
    println("Any event: $event")
}

eventBus.emit(ServerStarted(colleen)) // 不会触发上面的监听器

原因: listeners[event::class.java] 只会查找精确匹配的类型。

2. off() 方法性能问题

fun off(listener: EventListener<*>) {
    listeners.values.forEach { it.remove(listener) }
}

遍历所有事件类型的所有监听器,复杂度是 O(n*m)。应该记录监听器注册的事件类型。

3. 事件冒泡逻辑不完整

if (event.bubbles && !event.isPropagationStopped) {
    parent?.emit(event)
}

问题:

🟡 设计问题

4. data class 事件的陷阱

data class ServerStarted(override val target: Colleen) : AppEvent(target, false)

问题: data classequals/hashCode 只基于构造参数,不包括继承的属性:

val event1 = ServerStarted(colleen)
event1.stopPropagation()

val event2 = event1.copy()
// event2.isPropagationStopped == false! 😱

5. 线程安全问题

var isPropagationStopped: Boolean = false
    private set

在多线程环境下,这个变量应该是 @Volatile 或使用 AtomicBoolean

6. 异常处理过于宽泛

try {
    (listener as EventListener<T>).handler.accept(event)
} catch (e: Exception) {
    logger.error("Error in event listener: ${e.message}")
}

吞掉所有异常可能隐藏严重bug。应该至少记录堆栈跟踪,或提供错误处理策略。

📝 改进建议

完整优化版本

sealed class AppEvent(
    open val target: Colleen,
    val bubbles: Boolean = true,
) {
    var currentTarget: Colleen? = null
        internal set

    @Volatile
    private var _propagationStopped: Boolean = false
    val isPropagationStopped: Boolean 
        get() = _propagationStopped

    fun stopPropagation() {
        _propagationStopped = true
    }

    val timestamp: Long = System.currentTimeMillis()
}

// 使用普通 class 而非 data class
class ServerStarted(override val target: Colleen) : AppEvent(target, false) {
    override fun toString() = "ServerStarted(target=$target)"
}

class EventListener<T : AppEvent>(
    val eventType: Class<out AppEvent>, // 记录类型,优化off()
    val handler: Consumer<T>,
)

class EventBus {
    internal var parent: EventBus? = null

    @PublishedApi
    internal val listeners =
        ConcurrentHashMap<Class<out AppEvent>, CopyOnWriteArrayList<EventListener<out AppEvent>>>()

    inline fun <reified T : AppEvent> on(
        includeSubtypes: Boolean = false,
        noinline handler: (T) -> Unit
    ): EventListener<T> {
        return on(T::class.java, includeSubtypes, Consumer(handler))
    }

    fun <T : AppEvent> on(
        clazz: Class<T>,
        includeSubtypes: Boolean = false,
        handler: Consumer<T>
    ): EventListener<T> {
        val listener = EventListener(clazz, handler)
        
        if (includeSubtypes) {
            // 如果需要监听子类型,需要特殊处理
            // 这里简化:只注册到具体类型
            logger.warn("includeSubtypes not fully implemented yet")
        }
        
        listeners.computeIfAbsent(clazz) { CopyOnWriteArrayList() }.add(listener)
        return listener
    }

    fun off(listener: EventListener<*>) {
        // 优化: 直接从对应类型的列表中移除
        listeners[listener.eventType]?.remove(listener)
    }

    fun <T : AppEvent> emit(event: T) {
        // 设置当前目标
        event.currentTarget = event.target
        
        val eventListeners = listeners[event::class.java]
        
        eventListeners?.forEach { listener ->
            if (event.isPropagationStopped) return@forEach
            
            @Suppress("UNCHECKED_CAST")
            try {
                (listener as EventListener<T>).handler.accept(event)
            } catch (e: Exception) {
                // 记录完整堆栈,便于调试
                logger.error("Error in event listener for ${event::class.simpleName}", e)
                
                // 可选: 抛出包装后的异常或触发错误事件
                // throw EventListenerException("Listener failed", e)
            }
        }
        
        // 冒泡到父节点
        if (event.bubbles && !event.isPropagationStopped && parent != null) {
            // 更新 currentTarget 为父节点
            val originalTarget = event.currentTarget
            parent?.emit(event)
            event.currentTarget = originalTarget // 恢复
        }
    }
}

🎯 关键改进点

  1. 移除 data class: 避免 copy() 导致的状态丢失

  2. 添加 @Volatile: 保证线程安全

  3. 优化 off(): 从 O(n*m) 到 O(1)

  4. 完善 currentTarget: 正确处理冒泡过程

  5. 增强异常日志: 记录完整堆栈和事件类型

  6. 提供 includeSubtypes 选项: 为未来支持继承链监听预留接口

🤔 架构建议

考虑添加这些功能:

// 1. 事件优先级
class EventListener<T : AppEvent>(
    val eventType: Class<out AppEvent>,
    val handler: Consumer<T>,
    val priority: Int = 0 // 数字越大优先级越高
)

// 2. 一次性监听器
fun <T : AppEvent> once(handler: (T) -> Unit): EventListener<T>

// 3. 异步事件发射
suspend fun <T : AppEvent> emitAsync(event: T)

// 4. 事件拦截器(可修改事件)
fun <T : AppEvent> intercept(handler: (T) -> T)

你的框架目前是同步框架还是协程框架?这会影响事件系统的设计方向。