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
相关产品推荐
相关产品推荐

