《Spring揭秘》阅读笔记
package com.javadu.event;
import java.util.EventObject;
public class MethodExecutionEvent extends EventObject {
private String methodName;
public MethodExecutionEvent(Object source) {
super(source);
}
public MethodExecutionEvent(Object source, String methodName) {
super(source);
this.methodName = methodName;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
}
package com.javadu.event;
import java.util.EventListener;
public interface MethodExecutionEventListener extends EventListener {
void onMethodBegin(MethodExecutionEvent evt);
void onMethodEnd(MethodExecutionEvent evt);
}
EventListener接口的作用仅仅在于“标记”,具体要提供哪些功能需要开发者自己定义,而且,还需要为自己定义的接口提供一个默认的实现类——只有接口的话什么也做不了。
package com.javadu.event;
public class SimpleMethodExecutionEventListener implements MethodExecutionEventListener {
public void onMethodBegin(MethodExecutionEvent evt) {
String methodName = evt.getMethodName();
System.out.println("start to execute the method[" + methodName + "]");
}
public void onMethodEnd(MethodExecutionEvent evt) {
String methodName = evt.getMethodName();
System.out.println("finished to execute the method[" + methodName + "]");
}
}
public class MethodExecutionEventPublisher {
private List<MethodExecutionEventListener> listeners = new ArrayList<MethodExecutionEventListener>();
public void addMethodExecutionEventListener(MethodExecutionEventListener listener) {
this.listeners.add(listener);
}
public void methodToMonitor() {
MethodExecutionEvent event2Publish = new MethodExecutionEvent(this, "methodToMonitor");
//发布方法开始执行的事件
publishEvent(MethodExecutionStatus.BEGIN, event2Publish);
//执行实际的方法逻辑
//……
//发布方法执行结束的事件
publishEvent(MethodExecutionStatus.END, event2Publish);
}
protected void publishEvent(MethodExecutionStatus status, MethodExecutionEvent methodExecutionEvent) {
List<MethodExecutionEventListener> copyListeners = new ArrayList<MethodExecutionEventListener>(listeners);
for (MethodExecutionEventListener listener: copyListeners) { //发布事件,同时调用对应的监听器方法
if (MethodExecutionStatus.BEGIN.equals(status)) {
listener.onMethodBegin(methodExecutionEvent);
} else {
listener.onMethodEnd(methodExecutionEvent);
}
}
}
public void removeListener(MethodExecutionEventListener listener) {
if (this.listeners.contains(listener)) {
this.listeners.remove(listener);
}
}
public void removeAllListeners() {
this.listeners.clear();
}
public static void main(String[] args) {
MethodExecutionEventPublisher eventPublisher = new MethodExecutionEventPublisher();
eventPublisher.addMethodExecutionEventListener(new SimpleMethodExecutionEventListener()); //组合事件类和监听器
eventPublisher.methodToMonitor();//发布事件
}
}
Java SE中标准的自定义事件实现就是这个样子,涉及三个角色,即自定义事件类型、自定义的事件监听器和自定义的事件发布者,如下图所示:
JavaSE中自定义的事件结构图
Spring的ApplicationContext容器内部允许以 org.springframework.context.ApplicationEvent的形式发布事件, 容器内注册的org.springframework.context.ApplicationListener类型的bean定义会被ApplicationContext容器自动识别,它们负责监容器内发布的所有ApplicationEvent类型的事件。也就是说,一旦容器内发布ApplicationEvent及其子类型的事件,注册到容器的ApplicationListener就会对这些事件进行处理。
综上,Spring容器内部事件发布的类图描述如下:
Spring容器内部事件发布实现类图
Spring的ApplicationContext容器内的事件发布机制,主要用于单一容器内的简单消息通知和处理,并不适合分布式、多进程、多容器之间的事件通知。虽然可以通过Spring的Remoting支持,“曲折一点”来实现较为复杂的需求,但是难免弊大于利,失大于得。其他消息机制处理较复杂场景或许更合适。所以,我们应该在合适的地点、合适的需求分析的前提下,合理地使用Spring提供的ApplicationContext容器内的事件发布机制。