Axon框架使用指南(四):Event 处理

       事件侦听器是对传入事件起作用的组件。 他们通常根据命令模型所做的决定来执行逻辑。 通常,这涉及更新视图模型或将更新转发到其他组件,例如与第三方集成的组件。 在某些情况下,事件处理程序会根据事件的(模式)自己抛出事件,或者甚至发送命令来触发

定义事件处理程序

       在Axon中,一个对象可以用@EventHandler注释来声明一些EventHandler方法。该方法的声明参数定义了它将接收哪些事件。

Axon为以下参数类型提供开箱即用的支持:

  • 第一个参数始终是事件消息的有效负载。在事件处理程序不需要访问消息的有效负载的情况下,您可以在@EventHandler注释中指定预期的有效负载类型。指定时,使用下面指定的规则解析第一个参数。如果您希望将有效内容作为参数传递,请不要在注释中配置有效内容类型。
  • 使用@MetaDataValue注解的参数将使用注释中指示的键去解析元数据的值。如果该值不是必须的,required设置为false(默认),则在元数据值不存在时传递null。如果是必须的,则在元数据值不存在时解析器将不匹配,并防止调用该方法。
  • MetaData类型的参数将注入一个EventMessage的整个MetaData。
  • 用@Timestamp注解并且类型为java.time.Instant(或java.time.temporal.Temporal)将解析为EventMessage的时间戳。这个是事件产生的时间。
  • 用@SequenceNumber注解并且类型为java.lang.Long或long的参数将解析为DomainEventMessage的sequenceNumber。这提供了事件产生的顺序(在它发起的聚合范围内)。
  • Message类型的参数将接受整个EventMessage类型的数据传入, 如果第一个参数是消息类型的,如果没有指定泛型参数,那么它将匹配任何类型的事件, 由于类型擦除,在Axon无法检测到预期的载荷类型时,最好在Message的泛型参数中声明有效载荷类型。

     当使用Spring并且激活AxonConfiguration时(通过包含Axon Spring Boot Starter模块或者在@Configuration类中使用@EnableAxon注解),则任何其他参数都将解析为依赖注入的Bean。 这使您可以将资源直接注入到@EventHandler注解的方法中。

  您可以通过实现ParameterResolverFactory接口并创建一个名为/META-INF/service/org.axonframework.common.annotation.ParameterResolverFactory的文件来配置其他ParameterResolver,该文件包含实现类的完全限定名。 详情请参阅高级自定义设置。

在任何情况下,每个侦听器实例最多调用一个事件处理方法。 Axon将使用以下规则搜索最具体的事件处理方法:

  1. 在由this.getClass()返回类中,搜索所有注释了@EventHandler的方法
  2. 如果找到一个或多个方法可以将所有参数解析为值,则选择并调用传入的数据类型和方法的参数类型最匹配的方法
  3. 如果在该层次的层次结构中找不到方法,则父类型中查找,方式相同
  4. 达到类层次结构的顶层时,找不到合适的事件处理程序时,该事件将被忽略。
//假设EventB extends EventA

//并且EventC extends EventB

//并且 SubListener 是单例

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的处理程序方法将针对EventB的所有实例以及EventC(因为它扩展了EventB)而被调用。 换句话说,TopListener的处理程序方法根本不会收到EventC的任何调用。 由于EventA不可分配给EventB(它是它的父类),因此事件将由TopListener中的处理程序方法处理。

注册事件处理程序

       事件处理组件是使用EventHandlingConfiguration类定义的,该类被注册为全局Axon配置器的模块。 通常,应用程序将定义一个EventHandlingConfiguration,但更大的模块化应用程序可能会选择为每个模块定义一个。

要使用@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);

有关使用SpringAutoConfiguration注册事件处理程序的详细信息,请参阅事件处理配置章节。

查询处理

查询处理组件作用于传入的查询消息。 他们通常从Event监听器创建的视图模型中读取数据。 查询处理组件通常不会引发新事件或发送命令。

在Axon中,对象可以用@QueryHandler注解它们来声明多个QueryHandler方法。该方法的声明参数定义了它将接收哪些消息。

默认情况下,@QueryHandler注释的方法允许使用以下参数类型:

  • 第一个参数是查询消息的有效负载。它可以是Message或QueryMessage类型,如果@QueryHandler注解没有显式定义查询的名称,默认情况下,查询名称是查询有效负载的完全限定类名称。
  • 使用@MetaDataValue注解的参数将使用注解中指示的键解析元数据值。如果这个值是非必需的,required设为false(默认),则在元数据值不存在时会传递null。否则,元数据值不存在时解析器将不匹配,并防止在元数据值不存在时调用该方法。
  • MetaData类型的参数将注入一个QueryMessage的整个MetaData。
  • UnitOfWork类型的参数获取当前注入的工作单元。这允许查询处理程序注册要在工作单元的特定阶段执行的操作,或获取对其注册的资源的访问。
  • 类型为Message或QueryMessage的参数将获得完整的消息,同时包含有效内容和元数据。如果一个方法需要几个元数据字段或消息封装的其他属性,这很有用。

 您可以通过实现ParameterResolverFactory接口并创建一个名为/META-INF/service/org.axonframework.common.annotation.ParameterResolverFactory的文件来配置其他ParameterResolver,该文件包含实现类的完全限定名。 详情请参阅高级自定义设置章节。

在任何情况下,每个查询处理实例至多会调用一个查询处理程序方法。 Axon将使用以下规则查找最具体的调用方法:

  1. 在由this.getClass()返回的类中,查找所有注释的方法
  2. 如果找到一个或多个方法的所有参数可以匹配到值,则选择类型最匹配的方法
  3. 如果在该层次的层次结构中找不到方法,则在父类型中查找,匹配方式相同
  4. 达到类层次结构的顶层时,找不到合适的查询处理程序,此查询处理实例将被忽略。

请注意,与命令处理类似,与事件处理不同,查询处理不考虑查询消息的类层次结构。

//假设QueryB extends QueryA
//并且QueryC extends QueryB
//并且SubHandler是单例

public class TopHandler{
  @QueryHandler
  public MyResulthandle(QueryA query){
  }

  @QueryHandler
  public MyResulthandle(QueryB query){
  }

  @QueryHandler
  public MyResulthandle(QueryC query){
  }
}

public class SubHandler extends TopHandler{
  @QueryHandler
  public MyResulthandleEx(QueryB query){
  }
}

在上面的例子中,将调用SubHandler的处理方法来查询QueryB和结果MyResult;对QueryA和QueryC的查询和结果MyResult调用TopHandler的处理程序方法。

注册查询处理程序

可以为相同的查询名称和响应类型注册多个查询处理程序。 当分派查询时,客户可以指示他是想要一个结果还是来自所有可用的查询处理程序。

使用Spring

当使用SpringAutoConfiguration时,所有singleton Spring bean都会被扫描以查找具有@QueryHandler批注的方法。 对于找到的每个方法,都会在查询总线中注册一个新的查询处理程序。

使用配置API

也可以使用配置API来注册查询处理程序。 为此,请在Configurer类上使用registerQueryHandler方法:

// Sample query handler
public class MyQueryHandler{
  @QueryHandler
  public Stringecho(String echo){
   return echo;
  }
}

// To register yourquery handler
Configurer axonConfigurer =DefaultConfigurer.defaultConfiguration().registerQueryHandler(conf-> new MyQueryHandler);


猜你喜欢

转载自blog.csdn.net/wangli13860426642/article/details/80667868
今日推荐