有三個角色:java
一、事件源:事件產生的地方,能夠是一個類的任何方法,它主要職責是維護了一系列的監聽器的集合,定義在什麼地方發出監聽動做spring
二、事件:一個具體的動做,事件源能夠定義出多種事件,如改變name值的事件,改變id值的事件app
三、事件監聽器:它是監聽到特定的事件後要做出的動做,如接受到name改變的事件後發記錄下name改變的值框架
事件源中維護了一個listener的集合,這而且設定了setName setId的方法中去調用監聽器less
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"); } }
事件:主要是綁定事件源傳遞給listeneride
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(); } }
事件監聽器:當監聽源觸發事件後能夠回調到監聽器this
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等等spa
Spring中具體的應供實例以下:代理
如圖所示,SpringApplication這個類在啓動的時候,須要作框架事件的分發,在初始化的每步驟中都有特定的事件發佈給監聽器,code
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不要混淆了,我的感受這個名字起的有點不太好)