国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

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

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

瀏覽:2日期: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
相關文章:
主站蜘蛛池模板: 国产真实乱子伦精品视 | 久久看视频| 日本aaaaa级毛片 | 日韩不卡一区二区三区 | 亚洲国产一区在线二区三区 | 午夜性福 | 亚洲美女性视频 | 三级黄色在线观看 | 亚洲一区欧美一区 | 99精品免费 | 天堂va欧美ⅴa亚洲va一国产 | 成人高清在线观看 | 精品欧美亚洲韩国日本久久 | 91亚洲国产成人久久精品网站 | 久久91综合国产91久久精品 | 99国产在线观看 | 欧美在线观看一区 | 亚洲成a人不卡在线观看 | 午夜视频在线观看一区二区 | 奇米第四狠狠777高清秒播 | 久久er热这里只有精品免费 | 免费看片亚洲 | 亚洲天堂网在线观看视频 | 午夜大片免费男女爽爽影院久久 | 大片毛片女女女女女女女 | 亚洲偷自拍另类图片二区 | 日韩区| 国产精品成人一区二区三区 | 香蕉网影院在线观看免费 | 欧美亚洲一区二区三区四 | 69视频在线观看xxxxx | 男女视频免费看 | 久久精品一区二区三区中文字幕 | 在线观看久草视频 | 精品午夜寂寞影院在线观看 | 亚洲一区在线视频 | 久久精品午夜 | 色综合亚洲七七久久桃花影院 | 三级大片网站 | 无限观看社区在线视频 | 99精品国产成人一区二区在线 |