前言

在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);
}

// getter方法
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<>();

// 使用Lambda表达式添加监听器
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;

// 自定义Spring事件
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();
}

// getter方法省略
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; // PUT, REMOVE, CLEAR
private Object value;

public CacheEvent(String cacheKey, String operation, Object value) {
this.cacheKey = cacheKey;
this.operation = operation;
this.value = value;
}

// getter方法省略
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());
}
}
}
}
}

八、总结与最佳实践

(一)监听机制选择指南

  1. 简单场景:使用观察者模式或Java内置的PropertyChangeListener
  2. 复杂业务:使用自定义事件系统或注解驱动的监听机制
  3. Spring项目:优先使用Spring的事件机制
  4. 高性能要求:考虑异步处理和线程池

(二)设计原则

  • 单一职责:每个监听器只处理特定类型的事件
  • 松耦合:事件源和监听器之间避免直接依赖
  • 异常隔离:一个监听器的异常不应影响其他监听器
  • 性能考虑:对于耗时操作使用异步处理

(三)注意事项

  • 避免在监听器中执行耗时操作
  • 注意内存泄漏,及时移除不需要的监听器
  • 合理使用异步处理,避免线程安全问题
  • 做好异常处理和日志记录

监听机制是Java中实现事件驱动编程的重要工具,掌握其原理和实现方式对于编写高质量、可维护的代码具有重要意义。通过合理运用监听机制,可以让代码更加灵活、可扩展,同时提高系统的响应性和用户体验。


参考资料

  1. 官方文档

    • Oracle Java Documentation - Event Handling
    • Spring Framework Reference - Application Events
    • Java Beans Specification
  2. 设计模式相关

    • 《设计模式:可复用面向对象软件的基础》- GoF
    • 《Head First 设计模式》- Observer Pattern
  3. 技术文章

    • Java事件处理机制详解 - Oracle官方博客
    • Spring事件机制最佳实践 - Spring官方文档
    • 观察者模式在Java中的应用 - 技术博客