序
本文主要研究一下ddd-by-examples的DomainEvent
DomainEvent
public interface DomainEvent {
UUID getEventId();
UUID getAggregateId();
Instant getWhen();
}
DomainEvent接口定義了getEventId、getAggregateId、getWhen方法
DomainEvents
public interface DomainEvents {
void publish(DomainEvent event);
default void publish(List<DomainEvent> events) {
events.forEach(this::publish);
}
}
DomainEvents接口定義了publish方法,同時提供一個批量的publish方法
JustForwardDomainEventPublisher
@AllArgsConstructor
public class JustForwardDomainEventPublisher implements DomainEvents {
private final ApplicationEventPublisher applicationEventPublisher;
@Override
public void publish(DomainEvent event) {
applicationEventPublisher.publishEvent(event);
}
}
JustForwardDomainEventPublisher實現了DomainEvents接口,其publish方法通過spring的ApplicationEventPublisher來發布
MeteredDomainEventPublisher
@AllArgsConstructor
public class MeteredDomainEventPublisher implements DomainEvents {
private static final String DOMAIN_EVENTS = "domain_events";
private static final String TAG_NAME = "name";
private final DomainEvents delegate;
private final MeterRegistry metricsRegistry;
@Override
public void publish(DomainEvent event) {
delegate.publish(event);
metricsRegistry.counter(DOMAIN_EVENTS, TAG_NAME, event.getClass().getSimpleName()).increment();
}
}
MeteredDomainEventPublisher實現了DomainEvents接口,其publish先執行delegate.publish(event),然後遞增metrics的counter計數
StoreAndForwardDomainEventPublisher
@AllArgsConstructor
public class StoreAndForwardDomainEventPublisher implements DomainEvents {
private final DomainEvents eventsPublisher;
private final EventsStorage eventsStorage;
@Override
public void publish(DomainEvent event) {
eventsStorage.save(event);
}
@Scheduled(fixedRate = 3000L)
@Transactional
public void publishAllPeriodically() {
List<DomainEvent> domainEvents = eventsStorage.toPublish();
domainEvents.forEach(eventsPublisher::publish);
eventsStorage.published(domainEvents);
}
}
StoreAndForwardDomainEventPublisher實現了DomainEvents接口,其publish方法先通過eventsStorage.save(event)保存事件,之後有一個定時任務不斷執行eventsStorage.toPublish()獲取events,發佈事件,最後執行eventsStorage.published(domainEvents)
EventsStorage
public interface EventsStorage {
void save(DomainEvent event);
List<DomainEvent> toPublish();
void published(List<DomainEvent> events);
}
EventsStorage接口定義了save、toPublish、published方法
InMemoryEventsStorage
public class InMemoryEventsStorage implements EventsStorage {
//it's not thread safe, enough for testing
private final java.util.List<DomainEvent> eventList = Collections.synchronizedList(new ArrayList<>());
@Override
synchronized public void save(DomainEvent event) {
eventList.add(event);
}
@Override
synchronized public List<DomainEvent> toPublish() {
return List.ofAll(eventList);
}
@Override
synchronized public void published(List<DomainEvent> events) {
eventList.removeAll(events.asJava());
}
}
InMemoryEventsStorage實現了EventsStorage接口,其save方法添加event到eventList,其toPublish方法返回當時的eventList,其published方法從eventList移除指定的events
小結
ddd-by-examples定義了DomainEvent、DomainEvents接口,其中JustForwardDomainEventPublisher、MeteredDomainEventPublisher、StoreAndForwardDomainEventPublisher實現了DomainEvents接口;StoreAndForwardDomainEventPublisher藉助了EventsStorage,EventsStorage接口定義了save、toPublish、published方法。