前言
在Java开发中,监听机制是一种重要的编程模式,它允许我们在某个事件发生时自动执行相应的处理逻辑。这种机制广泛应用于GUI编程、Web开发、消息处理等场景中。本文将详细介绍Java中实现监听的多种方式,从基础的观察者模式到Spring框架的事件机制,帮助开发者深入理解和灵活运用监听机制。
监听机制的核心思想是”当某个事件发生时,自动通知所有关心该事件的监听者”,这种松耦合的设计模式使得代码更加灵活和可维护。
相关文章导航:
一、监听机制基础概念
(一)什么是监听机制
监听机制是一种基于事件驱动的编程模式,它包含以下核心组件:
- 事件源(Event Source):产生事件的对象
- 事件(Event):描述发生了什么的对象
- 监听器(Listener):处理事件的对象
- 事件分发器(Event Dispatcher):负责将事件分发给相应的监听器
(二)监听机制的优势
- 松耦合:事件源和监听器之间没有直接依赖
- 可扩展性:可以动态添加或移除监听器
- 代码复用:同一个监听器可以处理多种事件
- 异步处理:支持异步事件处理
(三)应用场景
- GUI事件处理(按钮点击、窗口关闭等)
- 业务逻辑解耦(用户注册后发送邮件、记录日志等)
- 系统监控(性能监控、异常监控等)
- 消息队列处理
- 数据库变更通知
二、观察者模式实现监听
(一)基础观察者模式
观察者模式是实现监听机制的经典设计模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| import java.util.*;
interface Observer { void update(String message); }
class Subject { private List<Observer> observers = new ArrayList<>(); private String state; public void addObserver(Observer observer) { observers.add(observer); } public void removeObserver(Observer observer) { observers.remove(observer); } public void notifyObservers(String message) { for (Observer observer : observers) { observer.update(message); } } public void setState(String state) { this.state = state; notifyObservers("状态已更改为: " + state); } public String getState() { return state; } }
class ConcreteObserver implements Observer { private String name; public ConcreteObserver(String name) { this.name = name; } @Override public void update(String message) { System.out.println(name + " 收到通知: " + message); } }
public class ObserverPatternDemo { public static void main(String[] args) { Subject subject = new Subject(); Observer observer1 = new ConcreteObserver("观察者1"); Observer observer2 = new ConcreteObserver("观察者2"); subject.addObserver(observer1); subject.addObserver(observer2); subject.setState("运行中"); subject.setState("已停止"); } }
|
(二)泛型观察者模式
使用泛型可以让观察者模式更加灵活:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| interface Event<T> { T getData(); String getEventType(); }
interface EventListener<T> { void onEvent(Event<T> event); boolean supports(String eventType); }
class EventManager { private Map<String, List<EventListener<?>>> listeners = new HashMap<>(); public <T> void addEventListener(String eventType, EventListener<T> listener) { listeners.computeIfAbsent(eventType, k -> new ArrayList<>()).add(listener); } public <T> void removeEventListener(String eventType, EventListener<T> listener) { List<EventListener<?>> eventListeners = listeners.get(eventType); if (eventListeners != null) { eventListeners.remove(listener); } } @SuppressWarnings("unchecked") public <T> void fireEvent(Event<T> event) { List<EventListener<?>> eventListeners = listeners.get(event.getEventType()); if (eventListeners != null) { for (EventListener<?> listener : eventListeners) { if (listener.supports(event.getEventType())) { ((EventListener<T>) listener).onEvent(event); } } } } }
class UserEvent implements Event<String> { private String data; private String eventType; public UserEvent(String eventType, String data) { this.eventType = eventType; this.data = data; } @Override public String getData() { return data; } @Override public String getEventType() { return eventType; } }
class UserEventListener implements EventListener<String> { private String name; public UserEventListener(String name) { this.name = name; } @Override public void onEvent(Event<String> event) { System.out.println(name + " 处理事件: " + event.getEventType() + ", 数据: " + event.getData()); } @Override public boolean supports(String eventType) { return eventType.startsWith("user."); } }
|
三、Java内置监听机制
(一)PropertyChangeListener
Java提供了内置的属性变更监听机制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport;
class User { private String name; private int age; private PropertyChangeSupport support; public User() { support = new PropertyChangeSupport(this); } public void addPropertyChangeListener(PropertyChangeListener listener) { support.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { support.removePropertyChangeListener(listener); } public void setName(String name) { String oldName = this.name; this.name = name; support.firePropertyChange("name", oldName, name); } public void setAge(int age) { int oldAge = this.age; this.age = age; support.firePropertyChange("age", oldAge, age); } public String getName() { return name; } public int getAge() { return age; } }
class UserPropertyListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { System.out.println("属性 " + evt.getPropertyName() + " 从 " + evt.getOldValue() + " 变更为 " + evt.getNewValue()); } }
public class PropertyChangeDemo { public static void main(String[] args) { User user = new User(); user.addPropertyChangeListener(new UserPropertyListener()); user.setName("张三"); user.setAge(25); user.setName("李四"); } }
|
(二)自定义事件监听器
创建自定义的事件监听器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
| import java.util.EventListener; import java.util.EventObject; import java.util.concurrent.CopyOnWriteArrayList;
class CustomEvent extends EventObject { private String message; private long timestamp; public CustomEvent(Object source, String message) { super(source); this.message = message; this.timestamp = System.currentTimeMillis(); } public String getMessage() { return message; } public long getTimestamp() { return timestamp; } }
interface CustomEventListener extends EventListener { void onCustomEvent(CustomEvent event); }
class EventPublisher { private CopyOnWriteArrayList<CustomEventListener> listeners = new CopyOnWriteArrayList<>(); public void addCustomEventListener(CustomEventListener listener) { listeners.add(listener); } public void removeCustomEventListener(CustomEventListener listener) { listeners.remove(listener); } public void publishEvent(String message) { CustomEvent event = new CustomEvent(this, message); for (CustomEventListener listener : listeners) { listener.onCustomEvent(event); } } }
class LogEventListener implements CustomEventListener { @Override public void onCustomEvent(CustomEvent event) { System.out.println("[LOG] " + new Date(event.getTimestamp()) + ": " + event.getMessage()); } }
class EmailEventListener implements CustomEventListener { @Override public void onCustomEvent(CustomEvent event) { System.out.println("[EMAIL] 发送邮件通知: " + event.getMessage()); } }
# 四、注解驱动的监听机制
## (一)自定义监听注解
使用注解可以让监听机制更加简洁和优雅:
```java import java.lang.annotation.*; import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.ConcurrentHashMap;
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface EventListener { String value() default ""; boolean async() default false; }
class EventBus { private Map<String, List<ListenerMethod>> listeners = new ConcurrentHashMap<>();
public void register(Object listener) { Class<?> clazz = listener.getClass(); Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) { EventListener annotation = method.getAnnotation(EventListener.class); if (annotation != null) { String eventType = annotation.value(); if (eventType.isEmpty()) { Class<?>[] paramTypes = method.getParameterTypes(); if (paramTypes.length > 0) { eventType = paramTypes[0].getSimpleName(); } }
listeners.computeIfAbsent(eventType, k -> new ArrayList<>()) .add(new ListenerMethod(listener, method, annotation.async())); } } }
public void post(Object event) { String eventType = event.getClass().getSimpleName(); List<ListenerMethod> eventListeners = listeners.get(eventType);
if (eventListeners != null) { for (ListenerMethod listenerMethod : eventListeners) { try { if (listenerMethod.isAsync()) { new Thread(() -> { try { listenerMethod.invoke(event); } catch (Exception e) { e.printStackTrace(); } }).start(); } else { listenerMethod.invoke(event); } } catch (Exception e) { e.printStackTrace(); } } } }
private static class ListenerMethod { private Object target; private Method method; private boolean async;
public ListenerMethod(Object target, Method method, boolean async) { this.target = target; this.method = method; this.async = async; method.setAccessible(true); }
public void invoke(Object event) throws Exception { method.invoke(target, event); }
public boolean isAsync() { return async; } } }
class OrderEvent { private String orderId; private String action;
public OrderEvent(String orderId, String action) { this.orderId = orderId; this.action = action; }
public String getOrderId() { return orderId; } public String getAction() { return action; } }
class OrderEventHandler {
@EventListener("OrderEvent") public void handleOrderCreated(OrderEvent event) { System.out.println("处理订单事件: " + event.getOrderId() + " - " + event.getAction()); }
@EventListener(value = "OrderEvent", async = true) public void sendNotification(OrderEvent event) { System.out.println("异步发送通知: " + event.getOrderId()); try { Thread.sleep(1000); System.out.println("通知发送完成: " + event.getOrderId()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }
public class AnnotationEventDemo { public static void main(String[] args) { EventBus eventBus = new EventBus();
eventBus.register(new OrderEventHandler());
eventBus.post(new OrderEvent("ORDER001", "CREATED")); eventBus.post(new OrderEvent("ORDER002", "UPDATED"));
try { Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }
|
(二)函数式监听器
使用Lambda表达式和函数式接口简化监听器的编写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| import java.util.function.Consumer; import java.util.concurrent.CopyOnWriteArrayList;
class FunctionalEventManager<T> { private CopyOnWriteArrayList<Consumer<T>> listeners = new CopyOnWriteArrayList<>();
public void addListener(Consumer<T> listener) { listeners.add(listener); }
public void removeListener(Consumer<T> listener) { listeners.remove(listener); }
public void fireEvent(T event) { listeners.forEach(listener -> listener.accept(event)); }
public void fireEventAsync(T event) { listeners.forEach(listener -> new Thread(() -> listener.accept(event)).start() ); } }
public class FunctionalListenerDemo { public static void main(String[] args) { FunctionalEventManager<String> eventManager = new FunctionalEventManager<>();
eventManager.addListener(message -> System.out.println("监听器1: " + message) );
eventManager.addListener(message -> System.out.println("监听器2: " + message.toUpperCase()) );
eventManager.addListener(System.out::println);
eventManager.fireEvent("Hello World!");
eventManager.fireEventAsync("Async Event!"); } }
|
五、Spring框架中的事件机制
(一)Spring事件发布与监听
Spring框架提供了强大的事件机制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service;
class UserRegisteredEvent extends ApplicationEvent { private String username; private String email;
public UserRegisteredEvent(Object source, String username, String email) { super(source); this.username = username; this.email = email; }
public String getUsername() { return username; } public String getEmail() { return email; } }
@Service class UserService { private ApplicationEventPublisher eventPublisher;
public UserService(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; }
public void registerUser(String username, String email) { System.out.println("用户注册: " + username);
eventPublisher.publishEvent(new UserRegisteredEvent(this, username, email)); } }
@Component class UserEventListener {
@EventListener public void handleUserRegistered(UserRegisteredEvent event) { System.out.println("用户注册事件处理: " + event.getUsername()); }
@EventListener @Async public void sendWelcomeEmail(UserRegisteredEvent event) { System.out.println("发送欢迎邮件给: " + event.getEmail()); }
@EventListener public void updateStatistics(UserRegisteredEvent event) { System.out.println("更新用户统计信息"); } }
|
(二)条件监听和事件过滤
Spring支持条件监听和事件过滤:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import org.springframework.context.event.EventListener; import org.springframework.core.annotation.Order;
@Component class ConditionalEventListener {
@EventListener(condition = "#event.username.length() > 5") public void handleLongUsername(UserRegisteredEvent event) { System.out.println("处理长用户名: " + event.getUsername()); }
@EventListener @Order(1) public void firstHandler(UserRegisteredEvent event) { System.out.println("第一个处理器"); }
@EventListener @Order(2) public void secondHandler(UserRegisteredEvent event) { System.out.println("第二个处理器"); } }
|
六、实际应用案例
(一)用户操作审计系统
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| class AuditEvent { private String userId; private String action; private String resource; private long timestamp;
public AuditEvent(String userId, String action, String resource) { this.userId = userId; this.action = action; this.resource = resource; this.timestamp = System.currentTimeMillis(); }
public String getUserId() { return userId; } public String getAction() { return action; } public String getResource() { return resource; } public long getTimestamp() { return timestamp; } }
class AuditListener {
@EventListener public void logAuditEvent(AuditEvent event) { System.out.println("审计日志: 用户 " + event.getUserId() + " 在 " + new Date(event.getTimestamp()) + " 对 " + event.getResource() + " 执行了 " + event.getAction()); }
@EventListener @Async public void saveToDatabase(AuditEvent event) { System.out.println("保存审计记录到数据库"); }
@EventListener(condition = "#event.action == 'DELETE'") public void alertOnDelete(AuditEvent event) { System.out.println("警告: 检测到删除操作!"); } }
|
(二)缓存失效通知系统
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| class CacheEvent { private String cacheKey; private String operation; private Object value;
public CacheEvent(String cacheKey, String operation, Object value) { this.cacheKey = cacheKey; this.operation = operation; this.value = value; }
public String getCacheKey() { return cacheKey; } public String getOperation() { return operation; } public Object getValue() { return value; } }
class CacheEventListener {
@EventListener public void onCacheUpdate(CacheEvent event) { if ("REMOVE".equals(event.getOperation())) { System.out.println("缓存失效: " + event.getCacheKey()); notifyOtherNodes(event.getCacheKey()); } }
@EventListener public void logCacheOperation(CacheEvent event) { System.out.println("缓存操作: " + event.getOperation() + " - " + event.getCacheKey()); }
private void notifyOtherNodes(String cacheKey) { System.out.println("通知集群节点缓存失效: " + cacheKey); } }
|
七、性能优化与最佳实践
(一)异步处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;
class AsyncEventManager { private ExecutorService executor = Executors.newFixedThreadPool(10); private List<Consumer<Object>> listeners = new CopyOnWriteArrayList<>();
public void addListener(Consumer<Object> listener) { listeners.add(listener); }
public CompletableFuture<Void> fireEventAsync(Object event) { List<CompletableFuture<Void>> futures = listeners.stream() .map(listener -> CompletableFuture.runAsync(() -> listener.accept(event), executor)) .collect(Collectors.toList());
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); }
public void shutdown() { executor.shutdown(); } }
|
(二)错误处理和重试机制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| class RobustEventManager { private List<EventListener> listeners = new CopyOnWriteArrayList<>();
public void fireEvent(Object event) { for (EventListener listener : listeners) { try { executeWithRetry(() -> listener.onEvent(event), 3); } catch (Exception e) { System.err.println("监听器执行失败: " + e.getMessage()); } } }
private void executeWithRetry(Runnable task, int maxRetries) { int attempts = 0; while (attempts < maxRetries) { try { task.run(); return; } catch (Exception e) { attempts++; if (attempts >= maxRetries) { throw e; } try { Thread.sleep(1000 * attempts); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); throw new RuntimeException(ie); } } } } }
|
(三)内存泄漏防护
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import java.lang.ref.WeakReference;
class WeakEventManager { private List<WeakReference<EventListener>> listeners = new CopyOnWriteArrayList<>();
public void addListener(EventListener listener) { listeners.add(new WeakReference<>(listener)); }
public void fireEvent(Object event) { Iterator<WeakReference<EventListener>> iterator = listeners.iterator(); while (iterator.hasNext()) { WeakReference<EventListener> ref = iterator.next(); EventListener listener = ref.get(); if (listener == null) { iterator.remove(); } else { try { listener.onEvent(event); } catch (Exception e) { System.err.println("监听器执行异常: " + e.getMessage()); } } } } }
|
八、总结与最佳实践
(一)监听机制选择指南
- 简单场景:使用观察者模式或Java内置的PropertyChangeListener
- 复杂业务:使用自定义事件系统或注解驱动的监听机制
- Spring项目:优先使用Spring的事件机制
- 高性能要求:考虑异步处理和线程池
(二)设计原则
- 单一职责:每个监听器只处理特定类型的事件
- 松耦合:事件源和监听器之间避免直接依赖
- 异常隔离:一个监听器的异常不应影响其他监听器
- 性能考虑:对于耗时操作使用异步处理
(三)注意事项
- 避免在监听器中执行耗时操作
- 注意内存泄漏,及时移除不需要的监听器
- 合理使用异步处理,避免线程安全问题
- 做好异常处理和日志记录
监听机制是Java中实现事件驱动编程的重要工具,掌握其原理和实现方式对于编写高质量、可维护的代码具有重要意义。通过合理运用监听机制,可以让代码更加灵活、可扩展,同时提高系统的响应性和用户体验。
参考资料
官方文档
- Oracle Java Documentation - Event Handling
- Spring Framework Reference - Application Events
- Java Beans Specification
设计模式相关
- 《设计模式:可复用面向对象软件的基础》- GoF
- 《Head First 设计模式》- Observer Pattern
技术文章
- Java事件处理机制详解 - Oracle官方博客
- Spring事件机制最佳实践 - Spring官方文档
- 观察者模式在Java中的应用 - 技术博客