@TransactionalEventListener 不起作用,因为 @EventListener 像相同上下文的魅力一样工作

vir*_*sha 2 java event-listener spring-boot

我正在从事 Spring Boot 应用程序的事件驱动设计。

代码由以下文件组成:

  1. Spring 启动:ApplicationEvent 文件,即 MyBusinessEvent.{java

    @Data
    @AllArgsConstructor
    public class MyBusinessEvent {
    
       private String data;
    
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 事件发布者文件:MyBusinessService.java

    @Slf4j
    @Service
    public class MyBusinessService {
    
        private final ApplicationEventPublisher applicationEventPublisher;
    
        @Autowired
        public MyBusinessService(
                ApplicationEventPublisher applicationEventPublisher) {
    
            this.applicationEventPublisher = applicationEventPublisher;
        }
    
        @Override
        public void save() {
            String data = "Testing event data";
            MyBusinessEvent event = new MyBusinessEvent(data);
            applicationEventPublisher.publishEvent(event);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 事件监听器:MyBusinessEventListener.java

    @Slf4j
    @Component
    public class MyBusinessEventListener {
    
        @EventListener
        public void handleEvent(MyBusinessEvent myBusinessEvent) {
            log.info("[MyBusinessEventListener] New event received with following data: {}", myBusinessEvent);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

关键是当侦听器文件包含时@EventListener,应用程序按预期工作,但当我这样做时@TransactionEventListener。例如:

  1. TransactionalEventListener : MyBusinessEventListener.java

    @Slf4j
    @Component
    public class MyBusinessEventListener {
    
        @TransactionalEventListener
        public void handleEvent(MyBusinessEvent myBusinessEvent) {
            log.info("[MyBusinessEventListener] New event received with following data: {}", myBusinessEvent);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

@TransactionalEventListener,它不会在所有的工作。

应用程序没有通过任何异常(甚至在运行时也没有),但没有按预期进行日志记录。

是否缺少任何配置?

Sha*_*tel 5

添加@Transactional注释MyBusinessService.save应该可以解决这个问题。

根据 java 文档,@TransactionalEventListener@Transactional边界内工作。

这里是什么文件说,

If the event is not published within the boundaries of a managed transaction, the
 * event is discarded unless the {@link #fallbackExecution} flag is explicitly set.
Run Code Online (Sandbox Code Playgroud)

如果您不希望在事务边界中使用您的服务方法,请使用 @TransactionalEventListener(fallbackExecution = true)

编辑:上述问题有三种可能的解决方案。

一世。标记class@Transactional被视为交易

@Transactional
@Service
public class MyBusinessService {

    private final ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    public MyBusinessService(
            ApplicationEventPublisher applicationEventPublisher) {

        this.applicationEventPublisher = applicationEventPublisher;
    }

    @Override
    public void save() {
        String data = "Testing event data";
        MyBusinessEvent event = new MyBusinessEvent(data);
        applicationEventPublisher.publishEvent(event);
    }
 }
Run Code Online (Sandbox Code Playgroud)

ii. 将具体的服务方式作为@Transactional

@Override
@Transactional
public void save() {
    String data = "Testing event data";
    MyBusinessEvent event = new MyBusinessEvent(data);
    applicationEventPublisher.publishEvent(event);
}
Run Code Online (Sandbox Code Playgroud)

三、如果您不希望在事务边界中使用您的服务方法,请使用

@Slf4j
@Component
public class MyBusinessEventListener {

    @TransactionalEventListener(fallbackExecution = true)
    public void handleEvent(MyBusinessEvent myBusinessEvent) {
        log.info("[MyBusinessEventListener] New event received with following data: {}", myBusinessEvent);
    }
}
Run Code Online (Sandbox Code Playgroud)