使用Spring Data Common时,它可以在聚合根的构造函数中注册域事件吗

时间:2018-08-29 09:17:53

标签: domain-events spring-data-commons

聚合将由某些application service创建,而不是由另一个聚合创建。

SomeAggregate aggregate = new SomeAggregate();
repo.save(aggregate);

期望的是,当应用程序服务结束时,将保存aggregate,并发布一个SomeAggregateCreated事件。我已经对其进行了测试,但它并不总是有效,有时在构造函数执行后并没有立即注册该事件。

这是老师班:

public class Teacher extends AbstractAggregateRoot<Teacher> {

    public Teacher() {
        registerEvent(new TeacherAdded(id, name));
    }
}

这是TeacherAdded

@AllArgsConstructor
@Getter
@ToString
@EqualsAndHashCode(callSuper = true)
public class TeacherAdded extends AbstractDomainEvent {
    private TeacherId teacherId;    
    private String name;
}

这是AbstractDomainEventDomainEvent

@Getter
@ToString()
@EqualsAndHashCode()
public abstract class AbstractDomainEvent implements DomainEvent {
    protected Date occurredOn;

    public AbstractDomainEvent() {
        this(new Date());
    }

    public AbstractDomainEvent(Date occurredOn) {
        this.occurredOn = occurredOn != null ? occurredOn : new Date();
    }

    @Override
    public Date occurredOn() {
        return occurredOn;
    }    
}

public interface DomainEvent {
    public Date occurredOn();
}

AbstractAggregateRoot复制org.springframework.data.domain.AbstractAggregateRoot<A>,并添加hasCapturedEvent方法进行测试。

public boolean hasCapturedEvent(DomainEvent event) {
    return domainEvents.contains(event);
}

如果我运行此命令:

// ...
TeacherAdded teacherAdded = new TeacherAdded(teacherId, teacherName);
Teacher teacher = new Teacher();
assertTrue(teacher.hasCapturedEvent(teacherAdded)); 

有时会失败,有时会成功。

1 个答案:

答案 0 :(得分:0)

答案是yes。构造函数注册的域事件可以正常发布和侦听。它们与通过常规方法注册的事件相同。

我在问题描述中提供的测试有缺陷。修改AbstractDomainEvent.hasCapturedEvent及其相关代码后,测试即可通过。

这是新的AbstractDomainEvent.hasCapturedEvent和测试方法。

    public boolean hasCapturedEvent(DomainEvent event, long occurredOnAdjustment) {
        if (occurredOnAdjustment <= 0) {
            return this.domainEvents.contains(event);
        } else {
            return this.domainEvents.stream().anyMatch(eventOnStream -> {
                return eventOnStream.equalsExcludedOccurTime(event)
                    && System.currentTimeMillis() - eventOnStream.occurredOn().getTime() <= occurredOnAdjustment;
            });
        }
    }

        TeacherAdded teacherAdded = new TeacherAdded(teacherId, teacherName);
        Teacher teacher = new Teacher();
        assertTrue(teacher.hasCapturedEvent(teacherAdded, 1000L)); 

这是新的TeacherAdded

public interface DomainEvent {
    public Date occurredOn();

    public default boolean equalsExcludedOccurTime(DomainEvent other) {
        return false;
    }
}

@lombok...
public class TeacherAdded extends AbstractDomainEvent {
    private TeacherId teacherId;    
    private String name;

    @Override
    public boolean equalsExcludedOccurTime(DomainEvent other) {
        if (!(other instanceof TeacherAdded)) {
            return false;
        } else {
            TeacherAdded other2 = (TeacherAdded)other;
            return Objects.equals(teacherId, other2.teacherId)
                && Objects.equals(name, other2.name);
        }
    }
}