乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      解密DDD:領(lǐng)域事件--系統(tǒng)解耦的終極武器

       漢無(wú)為 2023-09-27 發(fā)布于湖北

      1. 應(yīng)用場(chǎng)景

      假如你是訂單服務(wù)的一名研發(fā),正在開(kāi)發(fā)支付成功這個(gè)業(yè)務(wù)功能,在深度學(xué)習(xí) DDD 后,你寫(xiě)出了一組漂亮的代碼。

      @Transactional
      public void paySuccess(Long orderId){

          // 1. 獲取并驗(yàn)證訂單聚合根有效性
          Order order = this.orderRepository.getById(orderId);
          if (order == null){
              throw new IllegalArgumentException('訂單不存在');
          }

          // 2. 修改價(jià)格
          order.paySuccess();

          // 3. 保存 Order 聚合
          this.orderRepository.save(order);

          // 4. 通知物流服務(wù)進(jìn)行發(fā)貨
      }

      成功上線后,系統(tǒng)運(yùn)行穩(wěn)定。隨后,你又陸續(xù)接到更多需求,比如:

      1. 觸達(dá)通知:支付成功后,需要向用戶發(fā)送觸達(dá)短信,告知用戶已經(jīng)完成支付;

      2. 清理購(gòu)物車:用戶成功購(gòu)買商品后,把該商品從購(gòu)物車中移除;

      3. 確認(rèn)優(yōu)惠券:如果用戶購(gòu)買時(shí)使用了優(yōu)惠券,支付成功后調(diào)用優(yōu)惠券服務(wù)標(biāo)記優(yōu)惠券已經(jīng)被使用;

      4. 風(fēng)控管理:完成支付后,調(diào)用風(fēng)控系統(tǒng)提交訂單數(shù)據(jù),以便對(duì)當(dāng)前交易進(jìn)行風(fēng)險(xiǎn)評(píng)估;

      5. …..

      更多的需求還在路上,此時(shí)原本漂亮的代碼已經(jīng)逐漸失控,變得有些面目全非:

      @Transactional
      public void paySuccess(Long orderId){

          // 1. 獲取并驗(yàn)證訂單聚合根有效性
          Order order = this.orderRepository.getById(orderId);
          if (order == null){
              throw new IllegalArgumentException('訂單不存在');
          }

          // 2. 修改價(jià)格
          order.paySuccess();

          // 3. 保存 Order 聚合
          this.orderRepository.save(order);

          // 4. 通知物流服務(wù)進(jìn)行發(fā)貨

          // 5. 為用戶發(fā)生觸達(dá)短信
          // 發(fā)送觸達(dá)短信邏輯

          // 6. 清理購(gòu)物車

          // 7. 使用優(yōu)惠券,更新優(yōu)惠券狀態(tài)

          // 8. 提交風(fēng)控管理

          // 其他代碼

      }

      一些問(wèn)題慢慢的浮現(xiàn)出來(lái):

      1. 代碼極速腐化:paySuccess 代碼越來(lái)越多,想調(diào)整邏輯,需要從頭看到尾,一不小心就會(huì)出錯(cuò);

      2. 事務(wù)壓力變大:方法越來(lái)越長(zhǎng),事務(wù)邊界越來(lái)越大,占用數(shù)據(jù)庫(kù)連接的時(shí)間越來(lái)越長(zhǎng),系統(tǒng)性能快速下降;

      3. 依賴越來(lái)越復(fù)雜:OrderApplicationService 實(shí)現(xiàn)類中,產(chǎn)生了很對(duì)外部依賴,比如物流、短信、購(gòu)物車、優(yōu)惠券、風(fēng)控等;

      前期這些問(wèn)題你可能并不在意,直到有一天出現(xiàn)線上問(wèn)題:

      1. 三方短信通道出現(xiàn)問(wèn)題,影響訂單支付!

      2. 購(gòu)物車服務(wù)抖動(dòng),訂單狀態(tài)仍舊是待支付!

      3. 大數(shù)據(jù)風(fēng)控服務(wù)上線,訂單支付功能出現(xiàn)短時(shí)間不可用!

      聰明的你為了避免別人的服務(wù)到影響自己,悄悄的在每個(gè)業(yè)務(wù)調(diào)用時(shí)增加了 try-catch,但腐化仍舊在延續(xù)……

      如果你也意識(shí)到這個(gè)問(wèn)題,那正是引入領(lǐng)域事件的好時(shí)機(jī)。

      2. 領(lǐng)域事件

      領(lǐng)域事件是領(lǐng)域模型的重要組成部分,用于表示在領(lǐng)域中發(fā)生的一些重要的業(yè)務(wù)事情或者狀態(tài)變化,它用來(lái)捕獲領(lǐng)域中的一些變更,記錄事件發(fā)生時(shí)的業(yè)務(wù)狀態(tài),并將這些數(shù)據(jù)傳輸?shù)接嗛喎?,以開(kāi)展后續(xù)業(yè)務(wù)操作。

      領(lǐng)域事件有以下一些特點(diǎn):

      1. 不可變性:領(lǐng)域事件表示已經(jīng)發(fā)生的某種事實(shí),該事實(shí)在發(fā)生后便不會(huì)改變,通常將其建模為值對(duì)象;

      2. 解耦系統(tǒng):領(lǐng)域事件是事件驅(qū)動(dòng)的核心組成部分,用于解耦系統(tǒng)中的各個(gè)部分,使得系統(tǒng)變得更加靈活、可擴(kuò)展。通過(guò)發(fā)布訂閱模式,發(fā)布領(lǐng)域事件,讓訂閱者自行訂閱,從而達(dá)到解耦的目的;

      3. 最終一致性:通過(guò)領(lǐng)域事件來(lái)達(dá)到最終一致性,提高系統(tǒng)的穩(wěn)定性和性能;

      領(lǐng)域事件分為內(nèi)部領(lǐng)域事件和外部領(lǐng)域事件,想搞清楚兩者的區(qū)別,需要先回顧下“六邊形架構(gòu)”:

      圖片
      image
      1. 內(nèi)六邊形為領(lǐng)域模型,承載業(yè)務(wù)邏輯,內(nèi)部領(lǐng)域事件應(yīng)用于內(nèi)六邊形,主要用于服務(wù)或組件內(nèi)部,在同一個(gè)服務(wù)、應(yīng)用或限界上下文內(nèi)實(shí)現(xiàn)解耦。

      2. 外六邊形為基礎(chǔ)設(shè)施,承載技術(shù)復(fù)雜性,外部領(lǐng)域事件應(yīng)用于外六邊形。用于實(shí)現(xiàn)跨服務(wù)、應(yīng)用或限界上下文之間的通信,主要用于在微服務(wù)架構(gòu)中實(shí)現(xiàn)解耦,或者在不同子域或限界上下文之間傳播信息。

      2.1. 內(nèi)部領(lǐng)域事件

      內(nèi)部領(lǐng)域事件的主要目標(biāo)是在領(lǐng)域間傳播信息,以實(shí)現(xiàn)業(yè)務(wù)邏輯的分離和職責(zé)隔離。

      內(nèi)部領(lǐng)域事件通常使用同步或異步的方式在內(nèi)存中傳播。例如,在Java Spring中,可以使用ApplicationEventPublisher和@EventListener實(shí)現(xiàn)同步或異步的內(nèi)部領(lǐng)域事件,這些事件不會(huì)跨服務(wù)或應(yīng)用傳播。

      內(nèi)部領(lǐng)域事件工作在內(nèi)存中,在設(shè)計(jì)時(shí)需要注意以下幾點(diǎn):

      1. 直接使用 DDD 模型,無(wú)需轉(zhuǎn)化為 DTO:所有操作都是在內(nèi)存中完成,無(wú)需考慮對(duì)象粒度問(wèn)題,直接使用即可,沒(méi)有性能開(kāi)銷;

      2. 包含上下文的基礎(chǔ)信息:通常包含事件發(fā)生的時(shí)間、事件類型、事件源和與事件相關(guān)的任何其他數(shù)據(jù);

      3. 保持事件處理器職責(zé)單一:事件發(fā)布者與事件處理器之間為一對(duì)多的關(guān)系,事件處理器本身就是一個(gè)極佳的擴(kuò)展點(diǎn),不要為了減少事件處理器的數(shù)量而將邏輯耦合并到同一個(gè)處理器;

      4. 錯(cuò)誤處理和重試策略:為了確保事件處理的可靠性和健壯性,在實(shí)現(xiàn)事件監(jiān)聽(tīng)器時(shí),要考慮到可能的錯(cuò)誤場(chǎng)景,并設(shè)計(jì)相應(yīng)的異常處理和重試策略;

      5. 同步或異步處理:根據(jù)業(yè)務(wù)需求決定事件是同步還是異步處理。同步意味著在發(fā)布事件后,事件處理器將立即執(zhí)行,而發(fā)布者將等待其完成。異步意味著發(fā)布者將立即返回,事件處理將在另一個(gè)線程中進(jìn)行。在考慮使用哪種方式時(shí),需充分考慮資源競(jìng)爭(zhēng)、鎖定、超時(shí)等;

      Spring Event 是內(nèi)部領(lǐng)域事件落地的一把利器,稍后進(jìn)行詳解。

      2.2. 外部領(lǐng)域事件

      外部領(lǐng)域事件的主要目標(biāo)是在跨服務(wù)或子域?qū)崿F(xiàn)分布式的業(yè)務(wù)邏輯和系統(tǒng)間解耦。

      外部領(lǐng)域事件通常使用消息隊(duì)列(如Rocketmq、Kafka等)實(shí)現(xiàn)異步的跨服務(wù)傳播。

      外部領(lǐng)域事件工作在消息中間件之上,在設(shè)計(jì)時(shí)需要注意以下幾點(diǎn):

      1. 定制化 DTO:外部領(lǐng)域事件基于消息隊(duì)列進(jìn)行傳播,對(duì)于龐大且數(shù)據(jù)巨大的領(lǐng)域?qū)ο蠓浅2挥押茫瑫r(shí)為了防止內(nèi)部概念的外泄,無(wú)法直接使用,需要對(duì)領(lǐng)域事件進(jìn)行自定義;

      2. 事件序列化和反序列化:設(shè)計(jì)事件的序列化和反序列化機(jī)制,以便在不同系統(tǒng)之間傳輸和處理。常用的序列化格式包括JSON、XML、和二進(jìn)制序列化,如Avro、Protobuf等,需要充分考慮消息兼容問(wèn)題;

      3. 事件發(fā)布和訂閱:選擇一個(gè)支持可靠、高性能傳輸?shù)南⒅虚g件。例如,Kafka、RocketMQ等;

      4. 共享事件契約:契約包括:mq集群、topic、tag、Message 定義、Sharding Key 等;

      5. 錯(cuò)誤處理和重試策略:和處理內(nèi)部領(lǐng)域事件相似,需要考慮外部領(lǐng)域事件可能出現(xiàn)的錯(cuò)誤,并設(shè)計(jì)相應(yīng)的重試策略。特別是網(wǎng)絡(luò)傳輸過(guò)程中可能出現(xiàn)的丟失、重復(fù)或延遲問(wèn)題,需要設(shè)計(jì)相應(yīng)的冪等操作、消息去重和順序保證等措施;

      消息中間件是 外部領(lǐng)域事件 落地的關(guān)鍵技術(shù),由于篇幅原因,在此不做過(guò)多解釋。稍后會(huì)有文章進(jìn)行詳解。

      3. Spring  Event 機(jī)制

      Spring Event 是 Spring Framework 中的一個(gè)模塊,幫助在應(yīng)用程序中實(shí)現(xiàn)事件驅(qū)動(dòng)。它主要用于組件之間同步/異步通信,解耦事件發(fā)布者和事件消費(fèi)者。

      使用 Spring Event 包括以下步驟:

      1. 定義事件:創(chuàng)建一個(gè)事件類,該類封裝與特定事件相關(guān)的數(shù)據(jù);

      2. 創(chuàng)建事件監(jiān)聽(tīng)器:定義一個(gè)或多個(gè)事件監(jiān)聽(tīng)器,在監(jiān)聽(tīng)器中,處理特定類型的事件;

      3. 發(fā)布事件:調(diào)用ApplicationEventPublisher方法向外發(fā)布事件;

      在 Spring 中,事件的處理器可以通過(guò)三種方式來(lái)實(shí)現(xiàn):

      1. 基于接口的事件處理:通過(guò)實(shí)現(xiàn) ApplicationListener 接口并重寫(xiě) onApplicationEvent 方法來(lái)處理事件;

      2. 基于注解的事件處理:通過(guò)在方法上添加 @EventListener 或 @TransactionEventListener 注解來(lái)處理事件,可以指定事件的類型以及監(jiān)聽(tīng)的條件等;

      3. 基于異步事件處理:通過(guò)使用 @Async 注解來(lái)異步處理事件,可以提高應(yīng)用程序的響應(yīng)速度;

      3.1. 基于接口的事件處理

      由于與 Spring 存在強(qiáng)耦合,現(xiàn)在已經(jīng)很少使用,可以直接跳過(guò)。

      下面是一個(gè)基于接口的事件處理的示例代碼:

      @Component
      public class MyEventListener implements ApplicationListener<MyEvent{
          @Override
          public void onApplicationEvent(MyEvent event) {
              // 處理事件
              System.out.println('Received event: ' + event.getMessage());
          }
      }

      public class MyEvent {
          private String message;

          public MyEvent(String message) {
              this.message = message;
          }

          public String getMessage() {
              return message;
          }
      }

      @Component
      public class MyEventPublisher {
          @Autowired
          private ApplicationEventPublisher eventPublisher;

          public void publishEvent(String message) {
              MyEvent event = new MyEvent(message);
              eventPublisher.publishEvent(event);
          }
      }

      在這個(gè)示例中,MyEvent 是一個(gè)自定義的事件類,MyEventListener 是一個(gè)實(shí)現(xiàn)了 ApplicationListener 接口的監(jiān)聽(tīng)器,用于處理 MyEvent 事件,MyEventPublisher 是用于發(fā)布事件的類。

      當(dāng)應(yīng)用程序調(diào)用 MyEventPublisher 的 publishEvent 方法時(shí),會(huì)觸發(fā)一個(gè) MyEvent 事件,MyEventListener 中的 onApplicationEvent 方法將被自動(dòng)調(diào)用,從而處理這個(gè)事件。

      3.2. 基于注解的事件處理

      Spring 提供 @EventListener 和 @TransactionListener 兩個(gè)注解以簡(jiǎn)化對(duì)事件的處理。

      3.2.1. @EventListener

      Spring 的 EventListener 監(jiān)聽(tīng)器是一種相對(duì)于傳統(tǒng)的事件監(jiān)聽(tīng)方式更為簡(jiǎn)潔和靈活的事件機(jī)制。與傳統(tǒng)的事件機(jī)制不同,EventListener 不需要顯示地繼承特定的事件接口,而是使用注解標(biāo)識(shí)需要監(jiān)聽(tīng)的事件類型,然后通過(guò)一個(gè)單獨(dú)的監(jiān)聽(tīng)器類處理所有類型的事件。

      相比之下 EventListener 的優(yōu)勢(shì)主要有以下幾點(diǎn):

      1. 更加靈活:EventListener 不依賴于任何特定的事件接口,從而使得事件處理更加靈活,可以監(jiān)聽(tīng)和處理任意類型的事件;

      2. 更加簡(jiǎn)潔:相比傳統(tǒng)的事件監(jiān)聽(tīng)方式,使用 EventListener 可以避免一系列繁瑣的接口定義和實(shí)現(xiàn),簡(jiǎn)化了代碼結(jié)構(gòu),提升開(kāi)發(fā)效率;

      3. 更加松耦合:EventListener 將事件發(fā)布方和事件處理方分離,遵循松耦合的設(shè)計(jì)原則,提高了代碼的可維護(hù)性和擴(kuò)展性;

      4. 更加可測(cè)試:由于 EventListener 可以監(jiān)聽(tīng)和處理任意類型的事件,可以通過(guò)單元測(cè)試驗(yàn)證其功能是否正確,從而提高了測(cè)試的可靠性;

      以下是一個(gè)簡(jiǎn)單的例子:

      @Component
      public class MyEventListener{

          @EventListener
          public void onApplicationEvent(MyEvent event) {
              // 處理事件
              System.out.println('Received event: ' + event.getMessage());
          }
      }

      public class MyEvent {
          private String message;

          public MyEvent(String message) {
              this.message = message;
          }

          public String getMessage() {
              return message;
          }
      }

      @Component
      public class MyEventPublisher {

          @Autowired
          private ApplicationEventPublisher eventPublisher;

          public void publishEvent(String message) {
              MyEvent event = new MyEvent(message);
              eventPublisher.publishEvent(event);
          }
      }

      相比基于接口的事件處理,EventListener 是一種更加簡(jiǎn)潔、靈活、松耦合、可測(cè)試的事件機(jī)制,能夠有效地降低開(kāi)發(fā)的復(fù)雜度,提高開(kāi)發(fā)效率。

      3.2.2. @TransactionEventListener

      在 Spring 中,TransactionEventListner 和 EventListner 都是用于處理事件的接口。不同之處在于

      1. TransactionEventListner 是在事務(wù)提交后才會(huì)觸發(fā);

      2. 而 EventListner 則是在事件發(fā)布后就會(huì)觸發(fā);

      具體來(lái)說(shuō),在使用 Spring 的聲明式事務(wù)時(shí),可以在事務(wù)提交后觸發(fā)某些事件。這就是 TransactionEventListner 的應(yīng)用場(chǎng)景。而 EventListner 則不涉及事務(wù),可以用于在事件發(fā)布后觸發(fā)一些操作。

      下面是一個(gè)簡(jiǎn)單的示例,演示了如何使用 TransactionEventListner 和 EventListner:

      @Component
      public class MyEventListener {

          @EventListener
          public void handleMyEvent(MyEvent event) {
              // 處理 MyEvent
          }

          @TransactionalEventListener
          public void handleMyTransactionalEvent(MyTransactionalEvent event) {
              // 處理 MyTransactionalEvent
          }
      }

      @Service
      public class MyService {

          @Autowired
          private ApplicationEventPublisher eventPublisher;

          @Autowired
          private MyRepository myRepository;

          @Transactional
          public void doSomething() {
              // 做一些事情
              MyEntity entity = myRepository.findById(1L);
              // 發(fā)布事件
              eventPublisher.publishEvent(new MyEvent(this, entity));
              // 發(fā)布事務(wù)事件
              eventPublisher.publishEvent(new MyTransactionalEvent(this, entity));
          }
      }

      在這個(gè)例子中,MyEventListener 類定義了兩個(gè)方法,handleMyEvent 和 handleMyTransactionalEvent,分別處理 MyEvent 和 MyTransactionalEvent 事件。其中,handleMyTransactionalEvent 方法用 @TransactionalEventListener 注解標(biāo)記,表示它只會(huì)在事務(wù)提交后觸發(fā)。

      MyService 類中的 doSomething 方法使用 ApplicationEventPublisher 來(lái)發(fā)布事件。注意,它發(fā)布了兩種不同類型的事件:MyEvent 和 MyTransactionalEvent。這兩個(gè)事件會(huì)分別觸發(fā) MyEventListener 中的對(duì)應(yīng)方法。

      總的來(lái)說(shuō),Spring 的事件機(jī)制非常靈活,可以方便地?cái)U(kuò)展應(yīng)用程序的功能。TransactionEventListner 和 EventListner 這兩個(gè)接口的應(yīng)用場(chǎng)景有所不同,可以根據(jù)實(shí)際需求選擇使用。

      3.3.基于異步事件處理

      @Async是Spring框架中的一個(gè)注解,用于將一個(gè)方法標(biāo)記為異步執(zhí)行。使用該注解,Spring將自動(dòng)為該方法創(chuàng)建一個(gè)新線程,使其在后臺(tái)異步執(zhí)行,不會(huì)阻塞主線程的執(zhí)行。

      在實(shí)際應(yīng)用中,使用@Async可以大大提升應(yīng)用的并發(fā)處理能力,使得系統(tǒng)能夠更快地響應(yīng)用戶請(qǐng)求,提高系統(tǒng)的吞吐量。

      @Async 和 @EventListener 或 @TransactionEventListener 注解在一起使用時(shí),會(huì)產(chǎn)生異步的事件處理器。使用這種組合的方式,事件處理器會(huì)在單獨(dú)的線程池中執(zhí)行,以避免阻塞主線程。這種方式在需要處理大量事件或者事件處理器耗時(shí)較長(zhǎng)的情況下非常有用,可以有效提升應(yīng)用的性能和可伸縮性。同時(shí),Spring 框架對(duì)這種方式也提供了完善的支持,可以方便地使用這種方式來(lái)實(shí)現(xiàn)異步事件處理。

      下面是一個(gè)簡(jiǎn)單的示例代碼,演示了如何在 Spring 中使用 @Async 和 @EventListener 一起實(shí)現(xiàn)異步事件處理:

      @Component
      public class ExampleEventListener {

          @Async
          @EventListener
          public void handleExampleEvent(ExampleEvent event) {
              // 在新的線程中執(zhí)行異步邏輯
              // ...
          }
      }

      在這個(gè)示例中,ExampleEventListener 類中的 handleExampleEvent 方法使用了 @Async 和 @EventListener 注解,表示這個(gè)方法是一個(gè)異步事件監(jiān)聽(tīng)器。當(dāng)一個(gè) ExampleEvent 事件被觸發(fā)時(shí),這個(gè)方法會(huì)被異步地執(zhí)行。在這個(gè)方法中,可以執(zhí)行任何異步的邏輯處理,比如向隊(duì)列發(fā)送消息、調(diào)用其他服務(wù)等。

      備注:在使用 @Async 時(shí),需要根據(jù)業(yè)務(wù)場(chǎng)景對(duì)線程池進(jìn)行自定義,以免出現(xiàn)資源不夠的情況(Spring 默認(rèn)使用單線程處理@Async異步任務(wù))

      4. Spring Event 應(yīng)用場(chǎng)景分析

      綜上所述,當(dāng)領(lǐng)域事件發(fā)出來(lái)之后,不同的注解會(huì)產(chǎn)生不同的行為,簡(jiǎn)單匯總?cè)缦拢?/p>


      @EventListener@TransactionEventListener
      無(wú) @Async順序、同步執(zhí)行事務(wù)提交后、同步執(zhí)行
      有 @Async順序、異步執(zhí)行事務(wù)提交后、異步執(zhí)行

      4.1. @EventListener

      圖片
      image

      特點(diǎn):

      1. 順序執(zhí)行。調(diào)用 publish(Event) 后,自動(dòng)觸發(fā)對(duì) @EventListner 注釋方法的調(diào)用

      2. 同步執(zhí)行。使用主線程執(zhí)行,方法拋出異常會(huì)中斷調(diào)用鏈路,會(huì)觸發(fā)事務(wù)的回歸

      應(yīng)用場(chǎng)景:

      1. 事務(wù)消息表。在同一事務(wù)中完成對(duì)業(yè)務(wù)數(shù)據(jù)和消息表的修改

      2. 業(yè)務(wù)驗(yàn)證。對(duì)業(yè)務(wù)對(duì)象進(jìn)行最后一次驗(yàn)證,如果驗(yàn)證不通過(guò)直接拋出異常中斷數(shù)據(jù)庫(kù)事務(wù)

      3. 業(yè)務(wù)插件。在當(dāng)前線程和事務(wù)中執(zhí)行插件完成業(yè)務(wù)擴(kuò)展

      4.2. @TransactionEventListener

      圖片
      image

      特點(diǎn):

      1. 事務(wù)提交后執(zhí)行。調(diào)用 publish(Event) 時(shí),只是向上下文中注冊(cè)了一個(gè)回調(diào)器,并不會(huì)立即執(zhí)行;只有在事務(wù)提交后,才會(huì)觸發(fā) @TransactionEventListner 注釋方法的執(zhí)行

      2. 同步執(zhí)行。使用主線程執(zhí)行,方法拋出異常會(huì)中斷調(diào)用鏈路,但不會(huì)回歸事務(wù)(事務(wù)已提交,沒(méi)有辦法進(jìn)行回歸)

      應(yīng)用場(chǎng)景:

      1. 數(shù)據(jù)同步。事務(wù)提交后,將變更同步到 ES 或 Cache

      2. 記錄審計(jì)日志。只有在業(yè)務(wù)變更成功更新到數(shù)據(jù)庫(kù)時(shí)才進(jìn)行記錄

      備注:@TransactionEventLisnter 必須在事務(wù)上下文中,脫離上下文,調(diào)用不會(huì)生效

      4.3. @EventListener + @Async

      圖片
      image

      特點(diǎn):

      1. 順序執(zhí)行。調(diào)用 publish(Event) 后,自動(dòng)觸發(fā)對(duì) @EventListner 注釋方法的調(diào)用

      2. 異步執(zhí)行。使用獨(dú)立的線程池執(zhí)行任務(wù),方法拋出異常對(duì)主流程沒(méi)有任何影響

      應(yīng)用場(chǎng)景:

      1. 記日志明細(xì)日志,輔助排查問(wèn)題

      4.4. @TransactionEventListener + @Async

      圖片
      image

      特點(diǎn):

      1. 事務(wù)提交后執(zhí)行。調(diào)用 publish(Event) 時(shí),只是向上下文中注冊(cè)了一個(gè)回調(diào)器,并不會(huì)立即執(zhí)行;只有在事務(wù)提交后,才會(huì)觸發(fā)對(duì) @TransactionEventListner 注釋方法的調(diào)用

      2. 異步執(zhí)行。使用獨(dú)立的線程池執(zhí)行任務(wù),方法拋出異常對(duì)主流程沒(méi)有任何影響

      應(yīng)用場(chǎng)景:
      異步處理。記錄操作日志,異步保存數(shù)據(jù)等

      備注:@TransactionEventLisnter 必須在事務(wù)上下文中,脫離上下文,調(diào)用不會(huì)生效

      5. 小結(jié)

      領(lǐng)域事件是系統(tǒng)中的解耦利器,包括:

      1. 內(nèi)部事件 完成 領(lǐng)域模型內(nèi)各組件間的解耦;

      2. 外部事件 完成 領(lǐng)域服務(wù)間的解耦;

      Spring Event 是實(shí)現(xiàn)內(nèi)部領(lǐng)域事件解耦的利器,基于 事件監(jiān)聽(tīng)注解 和 同步/異步 兩組注解的組合為不同的應(yīng)用場(chǎng)景提供不同的支持。


      @EventListener@TransactionEventListener
      無(wú) @Async順序、同步執(zhí)行事務(wù)提交后、同步執(zhí)行
      有 @Async順序、異步執(zhí)行事務(wù)提交后、異步執(zhí)行

      外部領(lǐng)域事件 強(qiáng)依賴于消息中間件的使用,稍后會(huì)有文章進(jìn)行詳解。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多