27岁能干嘛,当然是继续学习。学海无涯,一叶扁舟,随便游。
了解ApplicationContext容器内部事件发布之前,我们先来了解一下java的自定义事件发布。本例大概如图所示
一,定义一个事件MethodExecutionEvent
(继承EventObject
)
二,定义一个监听器SimpleMethodExcutionEventListener
,设置onMethodBegin
和onMethodEnd
在事件开始前后监听事件。
三,定义一个类MethodExcutionEventPublisher
发布事件,及在不同的时机注册、调用、移除监听器。
具体代码,如下:
package event;
import java.util.EventObject;
//自定义事件类型:MethodExecutionEvent
public class MethodExecutionEvent extends EventObject {
private static final long serialVersionUID = 1L;
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 event;
import java.util.EventListener;
//自定义MethodExecutionEvent的事件监听器接口
public interface MethodExcutionEventListener extends EventListener {
/**
* 处理方法开始执行的时候发布的MethodExecutionEvent事件
* @param evt
*/
void onMethodBegin(MethodExecutionEvent evt);
/**
* 处理方法执行结束时发布的MethodExecutionEvent事件
* @param evt
*/
void onMethodEnd(MethodExecutionEvent evt);
}
package event;
//实现监听器
public class SimpleMethodExcutionEventListener implements MethodExcutionEventListener{
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+"].");
}
}
package event;
public enum MethodExecutionStatus {
BEGIN("1"),END("2");
private String name;
private MethodExecutionStatus(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package event;
import java.util.ArrayList;
import java.util.List;
//发布事件
public class MethodExcutionEventPublisher {
//事件监听器列表
private List<MethodExcutionEventListener> listeners = new
ArrayList<MethodExcutionEventListener>();
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<MethodExcutionEventListener> copyListeners =
new ArrayList<MethodExcutionEventListener>(listeners);
for (MethodExcutionEventListener listener:copyListeners) {
if (MethodExecutionStatus.BEGIN.equals(status)) {
listener.onMethodBegin(methodExecutionEvent);
} else {
listener.onMethodEnd(methodExecutionEvent);
}
}
}
//增加事件监听器
public void addMethodExecutionEventListener(MethodExcutionEventListener listener) {
this.listeners.add(listener);
}
//移除事件监听器
public void removeListener(MethodExcutionEventListener listener) {
if (this.listeners.contains(listener)) {
this.listeners.remove(listener);
}
}
//移除所有事件监听器
public void removeAllListeners() {
this.listeners.clear();
}
public static void main(String[] args) {
MethodExcutionEventPublisher eventPublisher =
new MethodExcutionEventPublisher();
eventPublisher.addMethodExecutionEventListener(new
SimpleMethodExcutionEventListener());
eventPublisher.methodToMonitor();
}
}
它的发布所用类和前面类似,主要是ApplicationEvent、ApplicationListener、ApplicationContext(继承了发布方法,但主要作用是调用其他的类来发布)
下面以以一个实例来了解他们。
执行过程是这样的,
第一,将MethodExcutionEventPublisher
需要的属性ApplicationEventPublisher
注册到xml文件
第二,将自定义的listener——MethodExcutionEventListener
注册到xml文件内
第三,将xml文件加载到spring的ApplicationContext
容器中。
这里有一点需要注意。
为啥执行了 this.eventPublisher.publishEvent(endEvt); 就可以调用MethodExcutionEventListener了呢?
因为我们将监听器注入到了容器中。
然后AbstractApplicationContext调用了ApplicationEventMulticaster去装载监听器。
第四,创建事件
第五,发布事件
package applicationEvent;
import org.springframework.context.ApplicationEvent;
import java.util.EventObject;
//自定义事件类型:MethodExecutionEvent
public class MethodExecutionEvent extends ApplicationEvent {
private static final long serialVersionUID = 1L;
private String methodName;
private MethodExecutionStatus methodExecutionStatus;
public MethodExecutionEvent(Object source) {
super(source);
}
public MethodExecutionEvent(Object source,String methodName,
MethodExecutionStatus methodExecutionStatus) {
super(source);
this.methodName = methodName;
this.methodExecutionStatus = methodExecutionStatus;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public MethodExecutionStatus getMethodExecutionStatus() {
return methodExecutionStatus;
}
public void setMethodExecutionStatus(MethodExecutionStatus methodExecutionStatus) {
this.methodExecutionStatus = methodExecutionStatus;
}
}
package applicationEvent;
public enum MethodExecutionStatus {
BEGIN("1"),END("2");
private String name;
private MethodExecutionStatus(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package applicationEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import java.util.EventListener;
//自定义MethodExecutionEvent的事件监听器接口
public class MethodExcutionEventListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent evt) {
if (evt instanceof MethodExecutionEvent) {
String methodName = ((MethodExecutionEvent) evt).getMethodName();
System.out.println("execute the method["+methodName+"].");
}
}
}
package applicationEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.ArrayList;
import java.util.List;
//发布事件
public class MethodExcutionEventPublisher implements ApplicationEventPublisherAware {
private ApplicationEventPublisher eventPublisher;
public void methodToMonitor() {
//创建事件
MethodExecutionEvent beginEvt =
new MethodExecutionEvent(this,"methodToMonitor",
MethodExecutionStatus.BEGIN);
//发布事件
this.eventPublisher.publishEvent(beginEvt);
//....事件具体执行
MethodExecutionEvent endEvt =
new MethodExecutionEvent(this,"methodToMonitor",
MethodExecutionStatus.END);
this.eventPublisher.publishEvent(endEvt);
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.eventPublisher = applicationEventPublisher;
}
public static void main(String[] args) {
//创建Spring的ioc容器,读取配置文件的beans.xml
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MethodExcutionEventPublisher evtPublisher = context.getBean(MethodExcutionEventPublisher.class);
evtPublisher.methodToMonitor();
}
}
DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="methodExecListener" class="applicationEvent.MethodExcutionEventListener">bean>
<bean id="evtPublisher" class="applicationEvent.MethodExcutionEventPublisher">bean>
beans>
java自定义事件发布
ApplicationContext容器内部事件发布