聊聊event-sourcing-cqrs的model
序
本文主要研究一下event-sourcing-cqrs的model
Event
public abstract class Event {
private final UUID aggregateId;
private final ZonedDateTime timestamp;
private final int version;
protected Event(UUID aggregateId, ZonedDateTime timestamp, int version) {
this.aggregateId = checkNotNull(aggregateId);
this.timestamp = checkNotNull(timestamp);
this.version = version;
}
public UUID getAggregateId() {
return aggregateId;
}
public ZonedDateTime getTimestamp() {
return this.timestamp;
}
public int getVersion() {
return version;
}
}
Event定义了aggregateId、timestamp、version属性
EventStore
public interface EventStore {
void store(UUID aggregateId, List<Event> newEvents, int baseVersion)
throws OptimisticLockingException;
List<Event> load(UUID aggregateId);
}
EventStore接口定义了store、load方法
Aggregate
public abstract class Aggregate {
private UUID id;
private int baseVersion;
private List<Event> newEvents;
protected Aggregate(UUID id) {
this(id, emptyList());
}
protected Aggregate(UUID id, List<Event> eventStream) {
checkNotNull(id);
checkNotNull(eventStream);
this.id = id;
eventStream.forEach(e -> {
apply(e);
this.baseVersion = e.getVersion();
});
this.newEvents = new ArrayList<>();
}
protected void applyNewEvent(Event event) {
checkArgument(event.getVersion() == getNextVersion(),
"New event version '%s' does not match expected next version '%s'",
event.getVersion(), getNextVersion());
apply(event);
newEvents.add(event);
}
private void apply(Event event) {
try {
Method method = this.getClass().getDeclaredMethod("apply", event.getClass());
method.setAccessible(true);
method.invoke(this, event);
} catch (InvocationTargetException e) {
Throwables.propagate(e.getCause());
} catch (NoSuchMethodException | IllegalAccessException e) {
throw new UnsupportedOperationException(
format("Aggregate '%s' doesn't apply event type '%s'", this.getClass(), event.getClass()),
e);
}
}
public UUID getId() {
return id;
}
public int getBaseVersion() {
return baseVersion;
}
public List<Event> getNewEvents() {
return ImmutableList.copyOf(newEvents);
}
protected int getNextVersion() {
return baseVersion + newEvents.size() + 1;
}
}
Aggregate定义了id、baseVersion、newEvents属性;其applyNewEvent方法会执行apply(event)及newEvents.add(event);apply方法通过反射执行event的apply方法
ValueObject
public abstract class ValueObject {
@Override
public boolean equals(Object o) {
return EqualsBuilder.reflectionEquals(this, o);
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
ValueObject覆盖了equals、hashCode、toString方法
Specification
public interface Specification<T> {
boolean isSatisfiedBy(T value);
}
Specification接口定义了isSatisfiedBy方法
小结
event-sourcing-cqrs-examples的model定义了Event、Aggregate、ValueObject抽象类以及EventStore、Specification接口。
doc
code-craft
spring boot , docker and so on 欢迎关注微信公众号: geek_luandun
推荐阅读
2022年终总结
最近两年开始陷入颓废中,博客也写的越来越少了。究其原因,主要还是陷入了职业倦怠期,最近一次跳槽感觉颇为失败,但是碍于给的薪资高,为了五斗米折腰,又加上最近行情不好,想要往外跳也跳不了,就这样子一直...
codecraft阅读 687
Java 编译器 javac 及 Lombok 实现原理解析
javac 是 Java 代码的编译器12,初学 Java 的时候就应该接触过。本文整理一些 javac 相关的高级用法。Lombok 库,大家平常一直在使用,但可能并不知道实现原理解析,其实 Lombok 实现上依赖的是 Java 编译器的注...
nullwy赞 10阅读 6k
与RabbitMQ有关的一些知识
工作中用过一段时间的Kafka,不过主要还是RabbitMQ用的多一些。今天主要来讲讲与RabbitMQ相关的一些知识。一些基本概念,以及实际使用场景及一些注意事项。
lpe234赞 8阅读 1.8k
Git操作不规范,战友提刀来相见!
年终奖都没了,还要扣我绩效,门都没有,哈哈。这波骚Git操作我也是第一次用,担心闪了腰,所以不仅做了备份,也做了笔记,分享给大家。问题描述小A和我在同时开发一个功能模块,他在优化之前的代码逻辑,我在开...
王中阳Go赞 5阅读 2k评论 2
Redis 发布订阅模式:原理拆解并实现一个消息队列
“65 哥,如果你交了个漂亮小姐姐做女朋友,你会通过什么方式将这个消息广而告之给你的微信好友?““那不得拍点女朋友的美照 + 亲密照弄一个九宫格图文消息在朋友圈发布大肆宣传,暴击单身狗。”像这种 65 哥通过朋...
码哥字节赞 6阅读 1.2k
NB的Github项目,看到最后一个我惊呆了!
最近看到不少好玩的、实用的 Github 项目,就来给大家推荐一把。中国制霸生成器最近在朋友圈非常火的一个小网站,可以在线标记 居住、短居、游玩、出差、路过 标记后可生成图片进行社区分享,标记过的信息会记录...
艾小仙赞 5阅读 1.5k评论 1
好好的系统,为什么要分库分表?
今天是《分库分表 ShardingSphere 原理与实战》系列的开篇文章,之前写过几篇关于分库分表的文章反响都还不错,到现在公众号:程序员小富后台不断的有人留言、咨询分库分表的问题,我也没想到大家对于分库分表的话...
程序员小富赞 3阅读 1.5k
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。