我读了这个blog和这个reference material,并确定Spring Data Commons Domain Events在Spring Data REST AbstractRepositoryEventListener事件(即onBeforeSave,onAfterDelete等)中应用时不起作用。
人:
@Entity @Data @EqualsAndHashCode(callSuper=true)
public class Person extends AbstractEntity {
// impl
public void markComplete(){
registerEvent(new PersonCompletedEvent());
}
}
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中的评论,这就是为什么应用程序事件在此示例中不起作用的原因。
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.
}
}
}
AbstractEntity:
import org.springframework.data.domain.AbstractAggregateRoot;
@MappedSuperclass @Data @EntityListeners(AuditingEntityListener.class)
public abstract class AbstractEntity extends AbstractAggregateRoot implements Identifiable<Long> {
// impl
}
PersonListener:
public class PersonListener {
@EventListener
public void processCompleted(PersonCompletedEvent event) {
// THIS IS NEVER FIRED
}
}
我已经对此进行了广泛的调试,看起来DomainEvents在RepositoryEntityController和EventPublishingRepositoryProxyPostProcessor$EventPublishingMethodInterceptor之间被删除了。
真正发生的是我的实体的不同实例实际上被截获,此时DomainEvents已不再存在。我可以确认@AfterDomainEventPublication clearDomainEvents()此时没有被调用,这让我相信它与domainEvents是瞬态的有关。
Spring Data REST&#39; s 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并且没有被触发。
更新:请阅读下面的评论,因为该实体已分离,因此无效。