<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring 事件驅(qū)動(dòng)模型

          共 5232字,需瀏覽 11分鐘

           ·

          2021-05-21 01:15

          0x01:spring事件驅(qū)動(dòng)組成

          spring事件驅(qū)動(dòng)由3個(gè)部分組成

          • ApplicationEvent:表示事件本身,自定義事件需要繼承該類。用來(lái)定義事件

          • ApplicationEventPublisherAware:事件發(fā)送器,需要實(shí)現(xiàn)該接口。主要用來(lái)發(fā)布事件。ApplicationContext 也實(shí)現(xiàn)了該接口,可以用于發(fā)布事件。

          Spring4.2之后,ApplicationEventPublisher自動(dòng)被注入到容器中,采用 Autowired 即可獲取。

          • ApplicationListener:事件監(jiān)聽(tīng)器接口。監(jiān)聽(tīng)類實(shí)現(xiàn) ApplicationListener  里onApplicationEvent方法即可。

          在 spring4.2 以后可以以更加簡(jiǎn)潔的方式來(lái)監(jiān)聽(tīng) event 的發(fā)布,監(jiān)聽(tīng)事件不必再實(shí)現(xiàn) ApplicationListener 接口了,只要在方法上添加注解 @EventListener即可。


          0x02:使用步驟詳解

          Spring中使用事件非常簡(jiǎn)單,只需要以下的幾個(gè)步驟:

          • 定義事件:繼承 ApplicationEvent

          • 定義監(jiān)聽(tīng):要么實(shí)現(xiàn) ApplicationListener 接口,要么在方法上添加 @EventListener 注解

          • 發(fā)布事件:調(diào)用 ApplicationContext.publishEvent() 或者 ApplicationEventPublisher.publishEvent()

          1、定義事件

          public class OrderCreateEvent extends ApplicationEvent {
              private final Order order;
              public OrderCreateEvent(Object source, Order order) {
                  super(source);
                  this.order = order;
              }
              public Order getOrder() {
                  return order;
              }
          }


          2、發(fā)送事件:publishEvent()方法

          @Autowired
           private ApplicationEventPublisher applicationEventPublisher;
              public void save(Order order) {
                  //生成訂單號(hào)
                  String orderNo = getOrderNo();
                  order.setOrderNo(orderNo);
                  log.info("訂單保存成功:" + order);
                  //發(fā)布訂單創(chuàng)建事件
                  applicationEventPublisher.publishEvent(new OrderCreateEvent(this, order));
              }


          3、訂閱事件(實(shí)現(xiàn)觀察者有2種方式)

          • 方式一:實(shí)現(xiàn) ApplicationListener 接口

          @Component
          public class OrderCreateEventListener implements ApplicationListener<OrderCreateEvent{
              @Override
              public void onApplicationEvent(OrderCreateEvent event) {
                  System.out.printf("實(shí)現(xiàn)ApplicationListener接口,監(jiān)聽(tīng)OrderCreateEvent事件");
              }
          }
          • 方式二:通過(guò)@EventListener注解,該會(huì)根據(jù)方法參數(shù)類型來(lái)自動(dòng)監(jiān)聽(tīng)相應(yīng)事件的發(fā)布。

          @Component
          @Slf4j
          public class OrderCreateEventListener {
              @EventListener (classes = {OrderCreateEvent.class}) //classes屬性指定處理事件的類型
              @Async //異步監(jiān)聽(tīng)
              @Order(0)//使用order指定順序,越小優(yōu)先級(jí)越高
              public void eventListener(OrderCreateEvent event) {
                  log.info("通過(guò)注解@EventListener和@Async,異步監(jiān)聽(tīng)OrderCreateEvent事件,orderId:" + event.getOrder().getOrderNo());
              }
          }


          如果要監(jiān)聽(tīng)多個(gè)事件類型的發(fā)布,可以在@EventListener(classes = {FaceEvent.class, ArmEvent.class})指定,spring 會(huì)多次調(diào)用此方法來(lái)處理多個(gè)事件。但是注意此時(shí),方法參數(shù)不能有多個(gè),否則會(huì)發(fā)生轉(zhuǎn)換異常,可以將使用多個(gè)事件的父類作為唯一的方法參數(shù)來(lái)接收處理事件,但除非必要否則并不推薦監(jiān)聽(tīng)多個(gè)事件的發(fā)布。

          如果有多個(gè)監(jiān)聽(tīng)器監(jiān)聽(tīng)同一事件,可以在方法上使用 spring 的 @order 注解來(lái)定義多個(gè)監(jiān)聽(tīng)器的順序,order越小,優(yōu)先級(jí)越高。

          @EventListener 還有一個(gè)屬性,condition()里可以使用 SPEL 表達(dá)式來(lái)過(guò)濾監(jiān)聽(tīng)到事件,即只有符合某種條件的才進(jìn)行接收處理。比如:

          @EventListener(condition = "event.message == 'message'")

          監(jiān)聽(tīng)多個(gè)事件:

          @EventListener({FaceEvent.class,ArmEvent.class})
          public void onApplicationEvent3(Object event{
                  if(event instanceof FaceEvent){
                      LOGGER.info("===> B 收到人臉事件:  {}",((FaceEvent) event).getEventData());
                  }else if(event instanceof ArmEvent){
                      ArmEvent armEvent = (ArmEvent) event;
                      LOGGER.info("===> B 收到臂膀事件:  {}",armEvent.getEventData());
                  }
          }


          注意事項(xiàng)

          • 事件沒(méi)要處理的監(jiān)聽(tīng)器,就會(huì)被拋棄。

          • 一個(gè)事件可以同時(shí)被多個(gè)監(jiān)聽(tīng)處理類監(jiān)聽(tīng)處理。

          • 默認(rèn)情況下事件是同步的,即事件被 publish 后會(huì)等待 Listener 的處理。如果發(fā)布事件處的業(yè)務(wù)存在事務(wù),監(jiān)聽(tīng)器處理也會(huì)在相同的事務(wù)中。

          • 如果對(duì)于事件的處理不想受到影響,可以onApplicationEvent方法上加@Async支持異步或者在有@EventListener的注解方法上加上@Async。注:?jiǎn)?dòng)類上同時(shí)要加上@EnableAsync

          利用@TransactionalEventListener實(shí)現(xiàn)監(jiān)聽(tīng)事件時(shí)的事務(wù)隔離

          很多時(shí)候,只有事務(wù)提交之后才會(huì)發(fā)布相應(yīng)的事件處理其他邏輯,比如用戶注冊(cè)之后,發(fā)送郵件或者短信。這時(shí)候就可以用注解 @TransactionalEventListener。

          @TransactionalEventListener 和 @EventListener 都可以監(jiān)聽(tīng)事件,但前者可以對(duì)發(fā)布事件和監(jiān)聽(tīng)事件進(jìn)行一些事務(wù)上的隔離。

          @TransactionalEventListener 是對(duì) @EventListener的一個(gè)擴(kuò)展,允許將事件的監(jiān)聽(tīng)器綁定到事務(wù)的某個(gè)階段。可以綁定到以下事務(wù)階段:

          • AFTER_COMMIT (默認(rèn)):事務(wù)提交后

          • AFTER_ROLLBACK ):事務(wù)回滾后

          • AFTER_COMPLETION ):事務(wù)完成,包括提交后和回滾后

          • BEFORE_COMMIT ):事務(wù)提交前

          @TransactionalEventListener 指不和發(fā)布事件的方法在同一個(gè)事務(wù)內(nèi),發(fā)布事件的方法事務(wù)結(jié)束后才會(huì)執(zhí)行本監(jiān)聽(tīng)方法,監(jiān)聽(tīng)邏輯內(nèi)發(fā)生異常不會(huì)回滾發(fā)布事件方法的事務(wù)。

          @TransactionalEventListener有一個(gè)屬性為 fallbackExecution,默認(rèn)為 false,指發(fā)布事件的方法沒(méi)有事務(wù)控制時(shí),監(jiān)聽(tīng)器不進(jìn)行監(jiān)聽(tīng)事件,此為默認(rèn)情況! fallbackExecution=true,則指發(fā)布事件的方法沒(méi)有事務(wù)控制時(shí),監(jiān)聽(tīng)方法仍可以監(jiān)聽(tīng)事件進(jìn)行處理。


          source: https://blog.csdn.net/kaihuishang666/article/details/107520480

          喜歡,在看



          瀏覽 27
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91豆花成人 | 日本无码免费视频 | 国产精品久久精品 | 国产一区二区AV | 午夜福利老司机 |