亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術(shù)文章
文章詳情頁

詳解基于Spring Data的領(lǐng)域事件發(fā)布

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

領(lǐng)域事件發(fā)布是一個(gè)領(lǐng)域?qū)ο鬄榱俗屍渌鼘ο笾雷约阂呀?jīng)處理完成某個(gè)操作時(shí)發(fā)出的一個(gè)通知,事件發(fā)布力求從代碼層面讓自身對象與外部對象解耦,并減少技術(shù)代碼入侵。

一、 手動(dòng)發(fā)布事件

// 實(shí)體定義@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(); }}// 領(lǐng)域服務(wù)@Servicepublic class ApplicationService { @Autowired private ApplicationEventPublisher applicationEventPublisher; @Autowired private DepartmentRepository departmentRepository; @Transactional(rollbackFor = Exception.class) public void departmentAdd(Department department) { departmentRepository.save(department); // 事件發(fā)布 applicationEventPublisher.publishEvent(new DepartmentEvent(department)); }}

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

二、 自動(dòng)發(fā)布事件

// 實(shí)體定義@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()); } // 事件發(fā)布后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(); }}// 領(lǐng)域服務(wù)@Servicepublic class ApplicationService { @Autowired private OrderRepository orderRepository; @Transactional(rollbackFor = Exception.class) public void saleOrderAdd(SaleOrder saleOrder) { orderRepository.save(saleOrder); }}

使用@DomainEvents定義事件返回的類型,必須是一個(gè)集合,使用@AfterDomainEventPublication定義事件發(fā)布后的回調(diào)。

此方法實(shí)事件類型定義在實(shí)體中,與領(lǐng)域服務(wù)完全解耦,沒有入侵。系統(tǒng)會(huì)在orderRepository.save(saleOrder)后自動(dòng)調(diào)用事件發(fā)布,另delete方法不會(huì)調(diào)用事件發(fā)布。

三、 事件監(jiān)聽

@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監(jiān)聽事件

@EventListener沒有事務(wù)支持,只要事件發(fā)出就可監(jiān)控到

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

上述情況會(huì)造成事務(wù)失敗回滾,但事件監(jiān)控端已經(jīng)執(zhí)行,可能導(dǎo)致數(shù)據(jù)不一致的情況發(fā)生

2. 使用@TransactionalEventListener監(jiān)聽事件

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

使用TransactionPhase.AFTER_COMMIT可在事務(wù)完成后,再執(zhí)行事件監(jiān)聽方法,從而保證數(shù)據(jù)的一致性

3. TransactionPhase.AFTER_ROLLBACK回滾事務(wù)問題

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

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

4. @Async異步事件監(jiān)聽

沒有此注解事件監(jiān)聽方法與主方法為一個(gè)事務(wù)。 使用此注解將脫離原有事務(wù),BEFORE_COMMIT也無法攔截事務(wù)提交前時(shí)刻 此注解需要配合@EnableAsync一起使用

四、 總結(jié)

通過對 @DomainEvents、@TransactionalEventListener的使用,在有效的解決領(lǐng)域事件發(fā)布的情況下,減少了對業(yè)務(wù)代碼的入侵,同時(shí)盡一步解決了數(shù)據(jù)一致性問題。

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

五、 源碼

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

到此這篇關(guān)于詳解基于Spring Data的領(lǐng)域事件發(fā)布的文章就介紹到這了,更多相關(guān)Spring Data 領(lǐng)域事件內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 久久伊人婷婷 | 最新内地三级在线观看 | 美国一级做a一级爱视频 | 综合久久99久久99播放 | 亚洲欧美日韩中文字幕久久 | 国产72av国片精品jk制服 | 伊人蕉久中文字幕无码专区 | 国内精品久久久久影院蜜芽 | 91青青视频 | 黄视频网站观看 | 久久精品亚洲 | 国产福利在线观看永久免费 | 成人综合网站 | 久久夜色tv网站免费影院 | 日韩在线视频线视频免费网站 | 欧美日韩亚洲m码色帝国 | 999人在线精品播放视频 | 国产伦码精品一区二区三区 | 亚洲人成在线观看男人自拍 | 真人一级一级特黄高清毛片 | 免费三级黄色片 | 欧美伦理三级 | 国产精品视频福利一区二区 | 在线亚洲欧国产精品专区 | 国产美女免费网站 | 亚洲午夜精品一区二区 | 香蕉黄色网 | 日日摸夜夜添夜夜添破第一 | 中日韩黄色大片 | 久草久操| ccmm123在线播放 | 国产日比| 国产国语一级毛片全部 | 免费区欧美一级毛片 | 欧美日韩亚洲视频 | 美女吊黑视频在线观看 | 国产麻豆精品hdvideoss | 日韩欧美一区二区在线观看 | 国产成人三级视频在线观看播放 | 国产爽片在线观看 | 高清欧美不卡一区二区三区 |