色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術文章
文章詳情頁

詳解基于Spring Data的領域事件發布

瀏覽:11日期:2023-09-13 08:18:25

領域事件發布是一個領域對象為了讓其它對象知道自己已經處理完成某個操作時發出的一個通知,事件發布力求從代碼層面讓自身對象與外部對象解耦,并減少技術代碼入侵。

一、 手動發布事件

// 實體定義@Entitypublic class Department implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer departmentId; @Enumerated(EnumType.STRING) private State state;}// 事件定義public class DepartmentEvent { private Department department; private State state; public DepartmentEvent(Department department) { this.department = department; state = department.getState(); }}// 領域服務@Servicepublic class ApplicationService { @Autowired private ApplicationEventPublisher applicationEventPublisher; @Autowired private DepartmentRepository departmentRepository; @Transactional(rollbackFor = Exception.class) public void departmentAdd(Department department) { departmentRepository.save(department); // 事件發布 applicationEventPublisher.publishEvent(new DepartmentEvent(department)); }}

使用applicationEventPublisher.publishEvent在領域服務處理完成后發布領域事件,此方法需要在業務代碼中顯式發布事件,并在領域服務里引入ApplicationEventPublisher類,但對領域服務本身有一定的入侵性,但靈活性較高。

二、 自動發布事件

// 實體定義@Entitypublic class SaleOrder implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer orderId; @Enumerated(EnumType.STRING) private State state; // 返回類型定義 @DomainEvents public List<Object> domainEvents(){ return Stream.of(new SaleOrderEvent(this)).collect(Collectors.toList()); } // 事件發布后callback @AfterDomainEventPublication void callback() { System.err.println('ok'); }}// 事件定義public class SaleOrderEvent { private SaleOrder saleOrder; private State state; public SaleOrderEvent(SaleOrder saleOrder) { this.saleOrder = saleOrder; state = saleOrder.getState(); }}// 領域服務@Servicepublic class ApplicationService { @Autowired private OrderRepository orderRepository; @Transactional(rollbackFor = Exception.class) public void saleOrderAdd(SaleOrder saleOrder) { orderRepository.save(saleOrder); }}

使用@DomainEvents定義事件返回的類型,必須是一個集合,使用@AfterDomainEventPublication定義事件發布后的回調。

此方法實事件類型定義在實體中,與領域服務完全解耦,沒有入侵。系統會在orderRepository.save(saleOrder)后自動調用事件發布,另delete方法不會調用事件發布。

三、 事件監聽

@Componentpublic class ApplicationEventProcessor { @EventListener(condition = '#departmentEvent.getState().toString() == ’SUCCEED’') public void departmentCreated(DepartmentEvent departmentEvent) { System.err.println('dept-event1:' + departmentEvent); } @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, condition = '#saleOrderEvent.getState().toString() == ’SUCCEED’') public void saleOrderCreated(SaleOrderEvent saleOrderEvent) { System.err.println('sale-event succeed1:' + saleOrderEvent); } @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT, condition = '#saleOrderEvent.getState().toString() == ’SUCCEED’') public void saleOrderCreatedBefore(SaleOrderEvent saleOrderEvent) { System.err.println('sale-event succeed2:' + saleOrderEvent); } @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK) public void saleOrderCreatedFailed(SaleOrderEvent saleOrderEvent) { System.out.println('sale-event failed:' + saleOrderEvent); }}

1. 使用@EventListener監聽事件

@EventListener沒有事務支持,只要事件發出就可監控到

@Transactional(rollbackFor = Exception.class)public void departmentAdd(Department department) { departmentRepository.save(department); applicationEventPublisher.publishEvent(new DepartmentEvent(department)); throw new RuntimeException('failed');}

上述情況會造成事務失敗回滾,但事件監控端已經執行,可能導致數據不一致的情況發生

2. 使用@TransactionalEventListener監聽事件

TransactionPhase.BEFORE_COMMIT 事務提交前 TransactionPhase.AFTER_COMMIT 事務提交后 TransactionPhase.AFTER_ROLLBACK 事務回滾后 TransactionPhase.AFTER_COMPLETION 事務完成后

使用TransactionPhase.AFTER_COMMIT可在事務完成后,再執行事件監聽方法,從而保證數據的一致性

3. TransactionPhase.AFTER_ROLLBACK回滾事務問題

@Async@TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK, condition = '#departmentEvent.getState().toString() == ’SUCCEED’')public void departmentCreatedFailed(DepartmentEvent departmentEvent) { System.err.println('dept-event3:' + departmentEvent);}

由于@DomainEvents作用在實體上的,只有剛orderRepository.save(saleOrder)執行成功后才會發送事件,故AFTER_ROLLBACK方法只會在同一事務中其它語句執行失敗或顯式rollback時才會執行,如果save方法執行失敗,將不會監聽到回滾事件。

4. @Async異步事件監聽

沒有此注解事件監聽方法與主方法為一個事務。 使用此注解將脫離原有事務,BEFORE_COMMIT也無法攔截事務提交前時刻 此注解需要配合@EnableAsync一起使用

四、 總結

通過對 @DomainEvents、@TransactionalEventListener的使用,在有效的解決領域事件發布的情況下,減少了對業務代碼的入侵,同時盡一步解決了數據一致性問題。

在分布式結構下,通過MQ發送事件通知給其它服務,為解決一致性問題,防止對方服務處理失敗可先將事件保久化到數據庫后,再重試。

五、 源碼

https://gitee.com/hypier/barry-jpa/tree/master/jpa-section-5

到此這篇關于詳解基于Spring Data的領域事件發布的文章就介紹到這了,更多相關Spring Data 領域事件內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
主站蜘蛛池模板: 亚洲天堂最新网址 | 亚洲成aⅴ人在线观看 | 亚洲精品高清久久 | 亚洲视频中文 | 欧美成人艳星在线播放 | 加勒比一本大道香蕉在线视频 | 看片亚洲 | 操小美女| 丝袜黄色片 | 亚洲国产成a人v在线 | 黄色激情在线 | 国产中文在线视频 | 国产精品久久亚洲一区二区 | 欧美另类亚洲一区二区 | 久久久久亚洲精品中文字幕 | 日韩一区二区三区在线免费观看 | 91在线亚洲 | 国内精品自产拍在线观看91 | 99久久久免费精品免费 | 韩国日本一级毛片免费视频 | 最新亚洲精品国自产在线 | 欧美一级网 | 亚洲欧美一区二区三区在线观看 | 中国老妇色xxxxx | 欧美满嘴射 | 国产成人精品一区二区免费 | 久草在线免费看 | 第一色区 | 国产日韩亚洲不卡高清在线观看 | 久久精品一区二区国产 | 九九99香蕉在线视频网站 | 激情丝袜美女视频二区 | 一级a欧美毛片 | 久久精品国产99久久72 | 精品欧美一区二区在线观看欧美熟 | 国产日产欧美精品一区二区三区 | 在线国产毛片 | 中文字幕一区二区三区 精品 | 特级一级毛片视频免费观看 | 国产精品青草久久久久福利99 | 综合国产 |