@TransactionalEventListener с AFTER_COMMIT, вызванным после ЗАВЕРШЕНИЯ

#java #spring-boot #transactions #spring-transactions

Вопрос:

Использование Пружинной загрузки 2.4.5.

У меня есть @TransactionalEventListener и более старомодный TransactionSynchronization . Я хочу выполнить как после фиксации транзакции, так и после выполнения заказа.

Вот образец теста.

 @SpringBootTest
@AutoConfigureTestDatabase
@EnableTransactionManagement
@ImportAutoConfiguration(DataSourceTransactionManagerAutoConfiguration.class)
class PostTxTest {

    @Configuration
    static class Config {
        @Bean
        SampleRepository sampleRepository(ApplicationEventPublisher eventPublisher) {
            return new SampleRepository(eventPublisher);
        }
        @TransactionalEventListener
        @Order(Ordered.HIGHEST_PRECEDENCE)
        void earlyListener(SampleEvent event) {
            System.out.println("early listener called !!!");
        }
    }

    static class SampleRepository {
        private final ApplicationEventPublisher eventPublisher;
        public SampleRepository(ApplicationEventPublisher eventPublisher) {
            this.eventPublisher = eventPublisher;
        }
        @Transactional
        public void execute() {
            eventPublisher.publishEvent(new SampleEvent());
            TransactionSynchronizationManager.registerSynchronization(new LateSynchronization());
        }
    }

    static class SampleEvent extends ApplicationEvent {
        public SampleEvent() {
            super("");
        }
    }

    static class LateSynchronization implements TransactionSynchronization {
        @Override
        public int getOrder() {
            return Ordered.LOWEST_PRECEDENCE;
        }
        @Override
        public void afterCommit() {
            System.out.println("late synchronization called !!!");
        }
    }

    @Test
    void test(@Autowired SampleRepository repository) {
        repository.execute();
    }
}
 

На выходе получается

 late synchronization called !!!
early listener called !!!
 

При отладке это выглядит AbstractPlatformTransactionManager так

 try {
    // here the TransactionSynchronization.afterCommit() is called
    triggerAfterCommit(status);
}
finally {
    // and here the TransactionalApplicationListenerSynchronization.afterCompletion() is called
    triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
}
 

TransactionalApplicationListenerSynchronization вызовет метод прослушивателя событий. Хотя для меня уже слишком поздно.

Вот вопросы:

  1. это специально или я что-то упускаю?
  2. задокументировано ли где-нибудь такое поведение?