You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java如何优雅实现携带对象的事件发送与监听功能?

你目前的实现确实不符合PropertyChange事件的设计语义,以下是几种更优雅的实现方案:

方案1:基于Java标准库自定义事件机制(无第三方依赖)

完全基于JDK自带的事件相关接口实现,不需要引入额外依赖,语义明确:

  • 第一步:自定义携带Payload的事件类,继承java.util.EventObject,可添加泛型约束保证类型安全
public class CustomPayloadEvent<T> extends EventObject {
    private final T payload;

    public CustomPayloadEvent(Object source, T payload) {
        super(source);
        this.payload = payload;
    }

    public T getPayload() {
        return payload;
    }
}
  • 第二步:自定义事件监听器接口,继承java.util.EventListener
public interface CustomPayloadListener<T> extends EventListener {
    void onPayloadReceived(CustomPayloadEvent<T> event);
}
  • 第三步:在Sender类中维护监听器列表,实现注册、移除、事件触发逻辑
public class Sender {
    // 使用CopyOnWriteArrayList保证多线程场景下的并发安全
    private final List<CustomPayloadListener<?>> listeners = new CopyOnWriteArrayList<>();

    // 注册监听器
    public <T> void addPayloadListener(CustomPayloadListener<T> listener) {
        listeners.add(listener);
    }

    // 移除监听器
    public <T> void removePayloadListener(CustomPayloadListener<T> listener) {
        listeners.remove(listener);
    }

    // 发送携带Payload的事件
    public <T> void firePayloadEvent(T payload) {
        CustomPayloadEvent<T> event = new CustomPayloadEvent<>(this, payload);
        for (CustomPayloadListener listener : listeners) {
            listener.onPayloadReceived(event);
        }
    }
}
  • 第四步:Receiver实现监听器接口处理事件
public class Receiver implements CustomPayloadListener<你要传递的对象类型> {
    @Override
    public void onPayloadReceived(CustomPayloadEvent<你要传递的对象类型> event) {
        你要传递的对象类型 payload = event.getPayload();
        // 直接处理Payload,不需要判断虚拟属性名
    }
}

使用示例:

Sender sender = new Sender();
Receiver receiver = new Receiver();
sender.addPayloadListener(receiver);
// 发送事件
sender.firePayloadEvent(待传递的对象实例);
方案2:基于Guava EventBus实现(普通Java项目推荐)

如果可以引入第三方依赖,Guava提供的EventBus是专门的发布-订阅事件组件,代码更简洁:

  • 首先引入Guava依赖(Maven示例)
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>最新稳定版本号</version>
</dependency>
  • Sender类实现事件发送逻辑
public class Sender {
    private final EventBus eventBus = new EventBus();

    // 注册监听器
    public void registerListener(Object listener) {
        eventBus.register(listener);
    }

    // 发送事件,任意对象都可以直接作为Payload
    public void sendPayload(Object payload) {
        eventBus.post(payload);
    }
}
  • Receiver类不需要实现接口,仅需添加注解即可
public class Receiver {
    // 订阅对应Payload类型的事件,EventBus会自动按参数类型匹配
    @Subscribe
    public void handlePayload(你要传递的对象类型 payload) {
        // 直接处理Payload
    }
}
方案3:基于Spring ApplicationEvent实现(Spring/SpringBoot项目推荐)

如果项目在Spring生态内,直接使用Spring自带的事件机制即可,无需自己管理监听器生命周期:

  • 自定义事件类,继承ApplicationEvent
public class PayloadEvent<T> extends ApplicationEvent {
    private final T payload;

    public PayloadEvent(Object source, T payload) {
        super(source);
        this.payload = payload;
    }

    public T getPayload() {
        return payload;
    }
}
  • Sender类注入事件发布器直接发事件
@Component
public class Sender {
    @Autowired
    private ApplicationEventPublisher eventPublisher;

    public void sendPayloadEvent(T payload) {
        eventPublisher.publishEvent(new PayloadEvent<>(this, payload));
    }
}
  • Receiver类添加@EventListener注解即可自动监听对应事件
@Component
public class Receiver {
    @EventListener
    public void handlePayloadEvent(PayloadEvent<你要传递的对象类型> event) {
        你要传递的对象类型 payload = event.getPayload();
        // 处理Payload
    }
}

内容的提问来源于stack exchange,提问作者Tomoms

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 19:54:05