事件機制 Spring 原始碼系列(4)

2021-07-27 13:46:55 字數 3943 閱讀 1872

目錄:

ioc容器beandefinition-spring 原始碼(1)

ioc容器依賴注入-spring 原始碼(2)

ioc容器beanpostprocessor-spring 原始碼(3)

事件機制-spring 原始碼(4)

事件源觸發事件後,將事件通知給***,***執行相應邏輯的過程

使用簡單的實現:

事件:

public

class eatevent extends

private

string status;

public

string getstatus()

public

void

setstatus(string status)

public

eatevent(object source)

}

***:

public

public

void

system.out.println("收到通知,可以去吃飯了");}}

觸發事件:

public

class testdo implements

private

public

void

dotest()

public

bean***ception

}

以上**是實際spring專案中經常會用到的,利用spring的事件機制,可以解耦各個具體***,在變化的需求中通過增減***來減少具體實現的改動。

spring核心是管理bean,而對於這種事件機制,天然有了比較好的實現基礎,可以想象這些事件bean在初始化時已經被管理器加入到某個登錄檔裡了,然後事件觸發時,就要找容器觸發。

原始碼實現部分:

public

void

publishevent(event,

null);}

protected

void

publishevent(object event, resolvabletype eventtype)

//if (event instanceof

}else}//

multicast right now if possible - or lazily once the multicaster is initialized

)

else

//publish event via parent context as well...

if (this.parent != null

)

else}}

protected

void

configurablelistablebeanfactory beanfactory =getbeanfactory();

//if

class

);

if(logger.isdebugenabled())

}else}}

public

void multicastevent(final

resolvabletype type = (eventtype != null ?eventtype : resolvedefaulteventtype(event));

executor executor =gettaskexecutor();

if (executor != null

) });

}else}}

object source =event.getsource();

class

> sourcetype = (source != null ? source.getclass() : null

); listenercachekey cachekey = new

listenercachekey(eventtype, sourcetype);

//quick check for existing entry on concurrenthashmap...

listenerretriever retriever = this

.retrievercache.get(cachekey);

if (retriever != null

)

if (this.beanclassloader == null ||(classutils.iscachesafe(event.getclass(),

this.beanclassloader) &&(sourcetype == null || classutils.iscachesafe(sourcetype, this

.beanclassloader))))

retriever = new listenerretriever(true

);

//獲取監聽者

//進快取

this

.retrievercache.put(cachekey, retriever);

return

listeners;}}

else}

resolvabletype eventtype, class

>sourcetype, listenerretriever retriever)

//遍歷全部監聽者,過濾出匹配的

if(supportsevent(listener, eventtype, sourcetype))

alllisteners.add(listener);}}

if (!listenerbeans.isempty())

alllisteners.add(listener);}}

}catch

(nosuchbeandefinitionexception ex) }}

annotationawareordercomparator.sort(alllisteners);

return

alllisteners;}

最下面的annotationawareordercomparator.sort用來排序監聽者的執行順序。繼承ordered即可。

這裡我們可以回顧一下這個refresh方法的具體**。

這裡牽涉到同步執行或非同步執行這些***的問題,預設spring是同步執行的,那麼在實際場景中我們會因為監聽者執行影響住流程,採用非同步的方式,如果沒有閱讀過原始碼,採取的方式可能會使用在publish的時候進行非同步化。

executor executor =gettaskexecutor();

if (executor != null

) });

}

public

private taskexecutor taskexecutor = new

taskexecutor()

};

protected

taskexecutor gettaskexecutor()

}

protected

void

errorhandler errorhandler =geterrorhandler();

if (errorhandler != null

)

catch

(throwable err)

}else

}

另外,回到最前面的例子中,注意eatevent中那個source屬性,代表**的意思,再呼叫publish方法時將this傳入,那麼在篩選監聽者的時候,就可以判斷是哪個**的bean發起的通知,再進行一次篩選是否執行的邏輯,如此就是監聽者可以過濾事件源了。

事件機制 Spring 原始碼系列(4)

目錄 ioc容器beandefinition spring 原始碼 1 ioc容器依賴注入 spring 原始碼 2 ioc容器beanpostprocessor spring 原始碼 3 事件機制 spring 原始碼 4 事件源觸發事件後,將事件通知給 執行相應邏輯的過程 使用簡單的實現 事件 ...

事件機制 Spring 原始碼系列(4)

目錄 ioc容器beandefinition spring 原始碼 1 ioc容器依賴注入 spring 原始碼 2 ioc容器beanpostprocessor spring 原始碼 3 事件機制 spring 原始碼 4 事件源觸發事件後,將事件通知給 執行相應邏輯的過程 使用簡單的實現 事件 ...

事件機制 Spring 原始碼系列(4)

目錄 ioc容器beandefinition spring 原始碼 1 ioc容器依賴注入 spring 原始碼 2 ioc容器beanpostprocessor spring 原始碼 3 事件機制 spring 原始碼 4 事件源觸發事件後,將事件通知給 執行相應邏輯的過程 使用簡單的實現 事件 ...