简体   繁体   English

使用自定义 ApplicationEventPublisher 发送 Spring 域事件

[英]Sending Spring domain events using a custom ApplicationEventPublisher

I'm trying to implement an application using Spring Boot/Spring Data, following DDD architecture guidelines.我正在尝试按照 DDD 架构指南使用 Spring Boot/Spring Data 实现一个应用程序。 I have an Aggregate Root which publish domain events using the method AbstractAggregateRoot::registerEvent() .我有一个聚合根,它使用AbstractAggregateRoot::registerEvent()方法发布域事件。 Furthermore, I need to intercept those events for Logging/Tracing purposes so I decided to make an experiment:此外,为了记录/跟踪目的,我需要拦截这些事件,因此我决定进行一个实验:

First, implement a custom ApplicationEvent Publisher一、实现自定义ApplicationEvent Publisher

public class CustomEventPublisher implements ApplicationEventPublisher {
    private final ApplicationEventPublisher publisher;

    private final Logger logger = getLogger(CustomEventPublisher.class);

    public CustomEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    @Override
    public void publishEvent(ApplicationEvent event) {
        logger.info("sending an event...");
        publisher.publishEvent(event);
    }

    //.....
}

And then registering as bean然后注册为bean

@Configuration
public class CustomEventPublisherConfig {

    @Bean
    @Primary
    public ApplicationEventPublisher getCustomEventPublisher(ApplicationEventPublisher publisher , RabbitTemplate rabbitTemplate) {
        return new CustomEventPublisher(publisher, rabbitTemplate);
    }
}

this works fine once I explicitly publish events from some sample object with an injected ApplicationEventPublisher一旦我使用注入的 ApplicationEventPublisher 从某个示例对象显式发布事件,这工作正常

public void pub() {
    publisher.publishEvent(new Event(this , 1));
}

@EventListener
public void sub(Event e) {
    this.value = e.getValue();
}

and I got the "sending an event..." log entry我得到了“发送事件...”日志条目

then I've tried to define the aggregate root然后我尝试定义聚合根

@Entity
public class AggregateRoot extends AbstractAggregateRoot {

    @Id
    @GeneratedValue
    private Long id;

    private int value = 0;

    public AggregateRoot setValue(int value) {
        registerEvent(new Event(this , value));
        return this;
    }
}

and

public void pub() {
    repository.save(new AggregateRoot().setValue(1));
}

Test pass again but I can clearly see that Spring Data is not using the CustomEventPublisher.测试再次通过,但我可以清楚地看到 Spring Data 没有使用 CustomEventPublisher。 I've tried to understand if there is some way to intercept repository.save() call and override the default behaviour, this approach could work even if needs to reinvent the wheel (I don't think that the domain event publishing code is so complicated though) but the only thing I've found is about Spring Data REST that is out of my scope我试图了解是否有某种方法可以拦截 repository.save() 调用并覆盖默认行为,即使需要重新发明轮子,这种方法也可以工作(我不认为域事件发布代码是如此虽然很复杂)但我发现的唯一一件事是关于 Spring Data REST 超出了我的范围

Any suggestion to overcome this problem?有什么建议可以克服这个问题吗?

Thanks in advance提前致谢

As far as I know, Spring does not provide a way to replace the publisher used by EventPublishingRepositoryProxyPostProcessor .据我所知,Spring 没有提供替换EventPublishingRepositoryProxyPostProcessor使用的发布者的EventPublishingRepositoryProxyPostProcessor And it seems to me that you have chosen not quite the right path to get what you want to achieve, so I am not answering your direct question, but your requirements described in the beginning.而且在我看来,您选择了不太正确的路径来实现您想要实现的目标,所以我不是在回答您的直接问题,而是在开始时描述您的要求。

I would advise you to register a listener using @EventListener and handle your event there:我建议您使用@EventListener注册一个监听器并在那里处理您的事件:

@EventListener
public void handleEvent(Event event) {
    System.out.println(event);
}

Or you can use @TransactionalEventListener to bind the listener to a transaction phase:或者您可以使用@TransactionalEventListener将侦听器绑定到事务阶段:

@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void handleEvent(Event event) {
    System.out.println(event);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM