一段时间后,我想出了解决方案,从投票中我相信其他人也面临同样的问题,这里是解决方案:
问题:我们可以触发领域事件的显式调用吗?
回答:是的,我们可以。在SpringBoot我们可以使用/AutowireApplicationEventPublisher接口,然后调用publishEvent(event)方法。
如果您要为 Db 集合和聚合创建单独的类,则需要在聚合中公开 DomainEvents 和 ClearingDomainEvents 的方法,因为 AbstractAggregateRoot<T> 将这些方法作为 protected。以下是在创建时引发事件的示例:
public class MyAggregateRootClass extends AbstractAggregateRoot<MyAggregateRootClass>
{
public MyAggregateRootClass(String property1, String property2) {
// set the fields here
registerEvent(new MyAggregateRootCreated(someArgs));
}
public Collection<Object> getDomainEvents() {
return super.domainEvents();
}
public void clearDomainEvents() {
super.clearDomainEvents();
}
}
存储库代码如下所示:
@Repository
@RequiredArgsConstructor // using lombok here, you can create a constructor if you want
public class MyAggregateRepository {
private final ApplicationEventPublisher eventPublisher;
private final AggregateMongoRepository repository;
public void save(MyAggregateRootClass aggToSave) {
AggregateDao convertedAgg = new AggregateDao(aggToSave);
repository.save(convertedAgg);
// raise all the domain events
for (Object event : aggToSave.getDomainEvents())
eventPublisher.publishEvent(event);
// clear them since all events have been raised
aggToSave.clearDomainEvents();
}
}
这是否意味着我们通常不应该创建两个不同的类,一个是AggregateRoot,另一个是用于在mongoDB 中存储聚合根的文档类?
回答:不,这并不意味着。 DDD 的目标是将infrastructure 与Domain 分开,并使Domain 与所有基础架构代码无关。如果它们都相同,则影响如下:
- 如果您要切换框架或将
Mongodb 与SQL 交换,在Aggregate Class 上添加@Document 注释将使您更改Domain。
- 将来,如果您的数据库架构需要更改,您必须同时更改聚合类或设置适配器类。
- 由于只有在业务需求发生变化而不是因为
infrastructure dependencies 而域才应该更改,所以将infrastructure annotations 潜入AggregateRoot 并不是最好的方法
那么,您什么时候才能真正摆脱对 Aggregate 和 Db Collection 使用相同的类?
如果您确实想保持简单并为两者使用相同的类而不是创建单独的类,那么请确保您确定以下内容:
- 如果您绝对确定自己永远不会切换数据库或更改框架。
- 你有一个简单的域模型,你不需要将
Aggregate 中的Entities 存储在一个单独的集合中,你不可能那些Entities 会成长为他们自己的Aggregates
最终取决于。随意加入 cmets,我会尽力回答所有问题,在堆栈上非常活跃。