我阅读了此博客和此参考资料,并确定在 Spring Data REST AbstractRepositoryEventListener 事件(即 onBeforeSave、onAfterDelete 等)中应用 Spring Data Commons Domain Events 时不起作用。
人:
@Entity @Data @EqualsAndHashCode(callSuper=true)
public class Person extends AbstractEntity {
// impl
public void markComplete(){
registerEvent(new PersonCompletedEvent());
}
}
人员已完成事件:
@Data public class PersonCompletedEvent {} // the RestBucks sample does not have OrderPaid event extend ApplicationEvent, I tried both ways and it still doesn't work.
更新:阅读 PersonHandler 中的注释,这就是为什么应用程序事件在此示例中不起作用的原因。
人员处理程序:
@Component @RepositoryEventHandler public class PersonHandler {
@PersistenceContext private EntityManager entityManager;
@Autowired private PersonRepo personRepo;
@HandleBeforeSave public void beforeSave(Person afterPerson){
/* UPDATE ::: This is the problem.
* This line is the reason why applicatin events do not fire.
* I need the before entity to detect delta's in the domain
* so I must detach it. However this causes events to be dropped.
*
* What's the best way to get the previous state?
*/
entityManager.detach(afterPerson);
Person beforePerson = personRepo.findOne(afterPerson.getId());
// impl
if (some condition) {
afterPerson.markComplete(); // this does add the event but it's never fired.
}
}
}
抽象实体:
import org.springframework.data.domain.AbstractAggregateRoot;
@MappedSuperclass @Data @EntityListeners(AuditingEntityListener.class)
public abstract class AbstractEntity extends AbstractAggregateRoot implements Identifiable<Long> {
// impl
}
个人监听器:
public class PersonListener {
@EventListener
public void processCompleted(PersonCompletedEvent event) {
// THIS IS NEVER FIRED
}
}
我已经对此进行了广泛的调试,看起来 DomainEvents 被丢弃在RepositoryEntityController和EventPublishingRepositoryProxyPostProcessor$EventPublishingMethodInterceptor之间的某个地方。
真正发生的是,我的 Entity 的另一个实例实际上被拦截了,此时 DomainEvents 不再存在。我可以确认此时没有调用 @AfterDomainEventPublication clearDomainEvents(),这让我相信它与 domainEvents 暂时性有关。
Spring Data REST 的RepositoryEntityController如下所示:
private ResponseEntity<ResourceSupport> saveAndReturn(Object domainObject, RepositoryInvoker invoker,
HttpMethod httpMethod, PersistentEntityResourceAssembler assembler, boolean returnBody) {
publisher.publishEvent(new BeforeSaveEvent(domainObject)); // 1
Object obj = invoker.invokeSave(domainObject); // 2
publisher.publishEvent(new AfterSaveEvent(obj));
在执行注释为 1 的行后,我的 domainObject 具有 domainEvents,这就是注释为 2 的行中的内容,invokeSave。当我的断点在RepositoryEntityController和EventPublishingRepositoryProxyPostProcessor$EventPublishingMethodInterceptor捕获时,它实际上是我的对象的不同实例(不同的对象 id),唯一缺少的是 domainEvents 并且没有任何东西被触发。
更新:阅读下面我的评论,它不起作用,因为实体已分离。