#java #spring #spring-data-jpa #event-driven-design #domain-events
#java #spring #spring-data-jpa #дизайн, управляемый событиями #домен-события
Вопрос:
Я пытаюсь реализовать приложение с использованием данных Spring Boot / Spring, следуя рекомендациям по архитектуре DDD. У меня есть совокупный корень, который публикует события домена с использованием метода AbstractAggregateRoot::registerEvent() . Кроме того, мне нужно перехватывать эти события для целей регистрации / отслеживания, поэтому я решил провести эксперимент:
Сначала внедрите пользовательский издатель ApplicationEvent
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);
}
//.....
}
А затем регистрация в качестве компонента
@Configuration
public class CustomEventPublisherConfig {
@Bean
@Primary
public ApplicationEventPublisher getCustomEventPublisher(ApplicationEventPublisher publisher , RabbitTemplate rabbitTemplate) {
return new CustomEventPublisher(publisher, rabbitTemplate);
}
}
это работает нормально, как только я явно публикую события из некоторого образца объекта с помощью введенного ApplicationEventPublisher
public void pub() {
publisher.publishEvent(new Event(this , 1));
}
@EventListener
public void sub(Event e) {
this.value = e.getValue();
}
и я получил запись в журнале «отправка события …»
затем я попытался определить совокупный корень
@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;
}
}
и
public void pub() {
repository.save(new AggregateRoot().setValue(1));
}
Повторите тест, но я ясно вижу, что Spring Data не использует CustomEventPublisher. Я попытался понять, есть ли какой-то способ перехватить вызов repository.save() и переопределить поведение по умолчанию, этот подход может сработать, даже если потребуется изобретать велосипед (я не думаю, что код публикации событий домена настолько сложен), но единственное, что я нашел, это примерноОстаток данных Spring, который выходит за рамки моей области
Есть предложения по преодолению этой проблемы?
Заранее спасибо
Комментарии:
1. Можете ли вы объяснить
registerEvent(new Event(this , value));
вAggregateRoot
2. @GSSwain docs.spring.io/spring-data/commons/docs/current/api/org/…
Ответ №1:
Насколько я знаю, Spring не предоставляет способа заменить издателя, используемого EventPublishingRepositoryProxyPostProcessor
. И мне кажется, что вы выбрали не совсем правильный путь, чтобы получить то, чего вы хотите достичь, поэтому я отвечаю не на ваш прямой вопрос, а на ваши требования, описанные в начале.
Я бы посоветовал вам зарегистрировать прослушиватель с помощью @EventListener
и обработать ваше событие там:
@EventListener
public void handleEvent(Event event) {
System.out.println(event);
}
Или вы можете использовать @TransactionalEventListener
для привязки прослушивателя к фазе транзакции:
@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void handleEvent(Event event) {
System.out.println(event);
}
Комментарии:
1. Хорошо, это то, что я обнаружил до сих пор. Кроме того, TransactionalEventListener не является необходимым для эксперимента