Design patterns
1、事件监听模式
有三个角色:
1、事件源:事件产生的地方,可以是一个类的任何方法,它主要职责是维护了一系列的监听器的集合,定义在什么地方发出监听动作
2、事件:一个具体的动作,事件源可以定义出多种事件,如改变name值的事件,改变id值的事件
3、事件监听器:它是监听到特定的事件后要作出的动作,如接受到name改变的事件后发记录下name改变的值
事件源中维护了一个listener的集合,这并且设定了setName setId的方法中去调用监听器
package com.springapp.beans.lisentner; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Created by zsw on 15-4-27. * 事件源 */ public class MyResourceObj{ private String id; private String name; private List<MyListener> listenerList = new ArrayList<MyListener>(); public List<MyListener> getListenerList() { return listenerList; } public void setListenerList(List<MyListener> listenerList) { this.listenerList = listenerList; } public void registeListener(MyListener listener){ this.listenerList.add(listener); } public void rmListener(MyListener listener){ this.listenerList.remove(listener); } public String getId() { return id; } public void setId(String id) { this.id = id; notifyAllListeners();
} public String getName() { return name; } public void setName(String name) { this.name = name; notifyAllListeners();
} private void notifyAllListeners(){//通知监听器执行用户自定义的方法 if(listenerList.size()>0){ Iterator iterator = listenerList.iterator(); while (iterator.hasNext()){ ((MyListener)iterator.next()).fireEvent(new MySetEvent(this)); } } } public static void main(String[] args) { MyResourceObj obj = new MyResourceObj(); obj.registeListener(new MySetListener()); obj.setName("zsw"); } }
事件:主要是绑定事件源传递给listener
package com.springapp.beans.lisentner;
/** * Created by zsw on 15-4-27. */ public class MySetEvent implements MyEvent {
public MySetEvent(){}
public MySetEvent(Object obj){ this.eventSourceObj = obj; }
private Object eventSourceObj;
public Object getEventSourceObj() { return eventSourceObj; }
public void setEventSourceObj(Object eventSourceObj) {//绑定事件源给Listener this.eventSourceObj = eventSourceObj; }
@Override public Object getSource() { return this.getEventSourceObj(); } }
事件监听器:当监听源触发事件后可以回调到监听器
package com.springapp.beans.lisentner;
/** * Created by zsw on 15-4-27. */ public class MySetListener implements MyListener {
@Override public void fireEvent(MyEvent event) { if(event.getClass().isAssignableFrom(MySetEvent.class)){ System.err.println("log message : my name or id is change:" + "{name is:"+((MyResourceObj) ((MySetEvent) event).getEventSourceObj()).getName() +",id is :"+ (((MyResourceObj) ((MySetEvent) event).getEventSourceObj()).getId())+"}"); } } }
Spring在在家的applicationContext中设置了好多Aware接口的实现类监听机制,每个都有自己的作用,可以设置ApplicationContext对象,获取生产自己的工厂BeanFactory等等
Spring中具体的应供实例如下:
如图所示,SpringApplication这个类在启动的时候,需要做框架事件的分发,在初始化的每步骤中都有特定的事件发布给监听器,
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
//创建事件发布者
SpringApplicationRunListeners listeners = getRunListeners(args);
//通过发布者类分发start时刻的事件
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
//发布上下文环境初始化完成的事件
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
流程图如下
Spring把事件源跟时间发布分离了,不集中在事件源里面的去维护代码,代码职责分离,它内部持有一个SpringApplicationRunListerns的实现类,这个类里面持有各种实现类集合,由他去继续分发给他的内部结合的实现类去处理发送事件给监听器
而SpringApplicationRunListerns的实现类(默认 : EventPublishingRunListener)内部持有了 一个事件广播器,真正的事件分发就是又这个事件广播器去实现动作,
SimpleApplicationEventMulticaster,他内部已经持有了初始化好的系统中所以的监听器实现类实例,
(注意:监听器的接口是ApplicationListern,而事件广播代理其接口是SpringApplicationRunListerns不要混淆了,个人感觉这个名字起的有点不太好)