Event Handling
Event listeners組件主要是將接收到的事件進(jìn)行處理。他們通常是根據(jù)命令模型來做具體的業(yè)務(wù)邏輯處理。通常涉及更新視圖模型或?qū)⒏罗D(zhuǎn)發(fā)給其他組件箱蝠,如第三方集成。在某些情況下沙兰,Event Handlers會根據(jù)事件的(模式)而自己發(fā)出事件涮毫,甚至發(fā)送命令來觸發(fā)進(jìn)一步的更改。
定義Event Handlers
在Axon中呢铆,一個對象可以用@EventHandler注解來聲明多個Event Handler方法晦鞋。方法的聲明參數(shù)定義了它將接收什么樣的事件。
Axon提供以下參數(shù)類型的開箱即用支持:
- 第一個參數(shù)總是事件消息的payload 棺克。在 Event Handlers不需要訪問消息的payload的情況下悠垛,您可以在@EventHandler注解中指定你所期望的payload類型。指定時逆航,使用下面指定的規(guī)則來解析第一個參數(shù)鼎文。如果您希望將payload作為參數(shù)傳遞渔肩,請不要在注解中配置payload類型因俐。
- 用@MetaDataValue注解的參數(shù),將用注解上的鍵對元數(shù)據(jù)值進(jìn)行解析周偎。如果這個值是false(默認(rèn))抹剩,則當(dāng)元數(shù)據(jù)值不存在時會傳遞null。如果值是true蓉坎,而元數(shù)據(jù)值不存時澳眷,這時解析器會發(fā)現(xiàn)錯誤,并阻止該方法的調(diào)用蛉艾。
- 參數(shù)為MetaData的話钳踊,那么將注入一個EventMessage的整個MetaData
- 使用@Timestamp注解并且類型為java.time.Instant(或java.time.temporal.Temporal)的參數(shù)將解析為EventMessage的時間戳。這是事件產(chǎn)生的時間勿侯。
- 用@SequenceNumber和類型java.lang.Long或long注解的參數(shù)將解析為DomainEventMessage的sequenceNumber拓瞪。這提供了事件生成的順序(在同一聚合范圍內(nèi)的生成順序)。
- Message類型的參數(shù)將會被整個EventMessage所注入(如果消息可分配給該參數(shù))助琐,如果第一個參數(shù)直接是一個Message類型祭埂,則它會匹配任何類型的事件,即使泛型參數(shù)可以提供幫助選擇兵钮,但是由于類型的擦除蛆橡,axon也不能檢測出預(yù)期的參數(shù)。在這種情況下掘譬,最好聲明有payload的參數(shù)泰演,然后是Message類型的參數(shù)。
7.當(dāng)使用Spring且Axon配置被激活時(通過包含Axon Spring Boot Starter模塊葱轩,或者在@Configuration文件中指定@EnableAxon)粥血,如果當(dāng)前的上下文中只有一個可入被spring注入的柏锄,那么任何其他參數(shù)都將被解析到autowired注入進(jìn)來的bean上。這使您可以將資源直接注入到@EventHandler注解的方法中复亏。
您可以通過實(shí)現(xiàn)ParameterResolverFactory接口并創(chuàng)建一個名為/META-INF/service/org.axonframework.common.annotation.ParameterResolverFactory的文件來配置其他ParameterResolver趾娃,該文件包含實(shí)現(xiàn)類的全名。詳情請 參考Advanced Customizations 缔御。
在所有情況下抬闷,每個event handler實(shí)例最多調(diào)用一個事件處理程序方法。 Axon將使用以下規(guī)則搜索最匹配的調(diào)用方法:
- 在類層次結(jié)構(gòu)(注:類的繼承關(guān)系)的實(shí)際實(shí)例層次(由this.getClass()返回)中耕突,將評估所有注解的方法
2.如果找到一個或多個方法可以將所有參數(shù)解析為一個值笤成,則選擇并調(diào)用最匹配(注:像java的多繼承接口同時繼承一個類的同一個方法調(diào)用沖突,也就是子接口或者實(shí)現(xiàn)優(yōu)先)的類型的方法
3.如果在這個級別的類層次結(jié)構(gòu)中沒有找到方法,那么超類的評估方法是相同的
4.當(dāng)達(dá)到類層次結(jié)構(gòu)的頂層時眷茁,還沒有找到合適的事件處理程序炕泳,該事件就被忽略掉。
// assume EventB extends EventA // and EventC extends EventB// and a single instance of SubListener is registered
public class TopListener {
@EventHandler
public void handle(EventA event) {
}
@EventHandler
public void handle(EventC event) {
}
}
public class SubListener extends TopListener {
@EventHandler
public void handle(EventB event) {
}
}
在上面的例子中上祈,SubListener的處理器方法將被調(diào)用EventB及EventC的所有實(shí)例(因?yàn)樗鼣U(kuò)展了EventB)培遵。換句話說,TopListener的處理程序方法根本不會收到EventC的任何調(diào)用登刺。由于EventA不能分配給EventB(它是它的父類)籽腕,所以這些將由TopListener中的處理程序方法處理。
注冊Event Handler
事件處理組件是使用EventHandlingConfiguration類定義的纸俭,該類是使用全局Axon 配置器注冊為模塊的皇耗。通常,應(yīng)用程序?qū)⒍x一個EventHandlingConfiguration揍很,但更大的模塊化應(yīng)用程序可能會選擇為每個模塊定義一個郎楼。
使用@EventHandler方法注冊對象,請使用EventHandlingConfiguration上的registerEventHandler方法:
// define an EventHandlingConfiguration
EventHandlingConfiguration ehConfiguration = new EventHandlingConfiguration()
.registerEventHandler(conf -> new MyEventHandlerClass());
// the module needs to be registered with the Axon Configuration
Configurer axonConfigurer = DefaultConfigurer.defaultConfiguration()
.registerModule(ehConfiguration);
有關(guān)使用Spring AutoConfiguration注冊事件處理程序的詳細(xì)信息窒悔,請參閱事件處理配置呜袁。