在最新的spring data commons 1.13框架中,新增了一个抽象聚合根类,我们可以继承这个聚合根类来完成领域事件模型。
说明:使你的领域层以来spring data commons在我眼里并不代表领域模型依赖了某一项特定的技术,spring data commons应该是一个通用的接口;因为底层你可以使用spring data jpa或spring data mongodb甚至于spring data redis等来实现具体的持久化任务。
下面我们来看一下新版的commons框架中增加的一个抽象聚合根类:
public class AbstractAggregateRoot {
/**
* 这会在lombok自动生成的getDomainEvents()方法上加上@DomainEvents注解,只有这个注册的domain事件或事件集合才会被扫描到事件总线去发布
*/
@Getter(onMethod = @__(@DomainEvents)) //
private transient final List<Object> domainEvents = new ArrayList<Object>();
/**
* Registers the given event object for publication on a call to a Spring Data repository's save method.
*
* @param event must not be {@literal null}.
* @return
*/
protected <T> T registerEvent(T event) {
Assert.notNull(event, "Domain event must not be null!");
this.domainEvents.add(event);
return event;
}
/**
* Clears all domain events currently held. Usually invoked by the infrastructure in place in Spring Data
* repositories.
*/
@AfterDomainEventPublication
public void clearDomainEvents() {
this.domainEvents.clear();
}
}
写一个自己的领域模型,比如订单类Order来继承这个AbstractAggregateRoot ,其中订单的其他属性(结构特征)我们先不考虑,因为这不是这篇文章的重点,我们只考虑它的业务方法。
public class Order extends AbstractAggregateRoot {
Order complete() {
registerEvent(new OrderCompletedEvent(this));
return this;
}
}
它有一个订单完成的业务方法,你可以注册一个或者多个完成订单时需要发布的事件,我们在这个complete方法中注册订单完成的领域事件,这个注册的事件会在你调用repository中的save()方法时触发,然后发布到事件总线。
执行仓储的save()时触发事件的代码见commons框架中的EventPublishingRepositoryProxyPostProcessor文件
org.springframework.data.repository.core.support.EventPublishingRepositoryProxyPostProcessor
现在你就可以对你的领域事件OrderCompletedEvent 进行建模,记录订单业务的发起事件、发起用户等等,我这里只是做个例子,具体根据业务场景而定。
public class OrderCompletedEvent {
private Order order;
@CreatedBy
private User user;
@CreatedDate
private Date createdDate;
public OrderCompletedEvent(Order order) {
this.order = order;
}
}