Jakarta EE CDI 事件 TransactionPhase.AFTER_SUCCESS 事件顺序颠倒
Jakarta EE CDI Event TransactionPhase.AFTER_SUCCESS event order is reverse
当使用 AFTER_SUCCESS
注释观察者方法时,事件的接收顺序与事务期间实际触发的顺序相反。
示例伪代码:
@Transactional
void test(){
pushEvent.fire( new PushEvent(10) );
pushEvent.fire( new PushEvent(20) );
pushEvent.fire( new PushEvent(30) );
}
观察者:
void onPushEvent( @Observes( during = TransactionPhase.AFTER_SUCCESS ) PushEvent event ){
System.out.println(event.getValue())
}
意外但观察到的结果:
30
20
10
这可以更改吗?
在我的项目中使用事件的线程本地缓冲区修复了此问题,该缓冲区在 AFTER_SUCCESS 上刷新并按照事件首先出现的顺序重播事件
ThreadLocal<List<PushEvent>> threadEventBufferHolder = ThreadLocal.withInitial( ArrayList::new );
void onPushEvent( @Observes( during = TransactionPhase.IN_PROGRESS ) PushEvent event ){
threadEventBufferHolder.get().add( event );
}
void onPushEventFailure( @Observes( during = TransactionPhase.AFTER_FAILURE ) PushEvent event ){
buffer.clear();
}
void onPushEventCommit( @Observes( during = TransactionPhase.AFTER_SUCCESS ) PushEvent event ){
List<PushEvent> buffer = threadEventBufferHolder.get();
buffer.forEach( this::doPrintlnValue );
buffer.clear();
}
删除了不相关的代码以便于阅读
当使用 AFTER_SUCCESS
注释观察者方法时,事件的接收顺序与事务期间实际触发的顺序相反。
示例伪代码:
@Transactional
void test(){
pushEvent.fire( new PushEvent(10) );
pushEvent.fire( new PushEvent(20) );
pushEvent.fire( new PushEvent(30) );
}
观察者:
void onPushEvent( @Observes( during = TransactionPhase.AFTER_SUCCESS ) PushEvent event ){
System.out.println(event.getValue())
}
意外但观察到的结果:
30
20
10
这可以更改吗?
在我的项目中使用事件的线程本地缓冲区修复了此问题,该缓冲区在 AFTER_SUCCESS 上刷新并按照事件首先出现的顺序重播事件
ThreadLocal<List<PushEvent>> threadEventBufferHolder = ThreadLocal.withInitial( ArrayList::new );
void onPushEvent( @Observes( during = TransactionPhase.IN_PROGRESS ) PushEvent event ){
threadEventBufferHolder.get().add( event );
}
void onPushEventFailure( @Observes( during = TransactionPhase.AFTER_FAILURE ) PushEvent event ){
buffer.clear();
}
void onPushEventCommit( @Observes( during = TransactionPhase.AFTER_SUCCESS ) PushEvent event ){
List<PushEvent> buffer = threadEventBufferHolder.get();
buffer.forEach( this::doPrintlnValue );
buffer.clear();
}
删除了不相关的代码以便于阅读