自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Spring-Context注解源碼之@EventListener

開發(fā) 前端
EventListenerMethodProcessor的processBean方法中,會遍歷已經(jīng)注冊的所有的bean,找到包含有被 @EventListener 標(biāo)注的方法。這些方法會被遍歷已經(jīng)創(chuàng)建的 EventListenerFactory 找到合適的工廠來生成 applicationListener,并將 applicationListener 注冊到容器的事件監(jiān)聽器列表。

[[410307]]

 注解說明

Annotation that marks a method as a listener for application events.

以注解的方式將一個方法標(biāo)記為事件監(jiān)聽器。如果對于spring事件監(jiān)聽機制還不了解的小伙伴點擊查看一文徹底搞懂spring事件監(jiān)聽機制

屬性說明

  1. public @interface EventListener { 
  2.  
  3.    /** 
  4.     * 同class 
  5.     */ 
  6.    @AliasFor("classes"
  7.    Class<?>[] value() default {}; 
  8.  
  9.    /** 
  10.     * 監(jiān)聽事件的類型 
  11.     * 如果這個屬性長度不為空,則以這個屬性的為準(zhǔn) 
  12.     * 如果這個屬性長度為空,則以被標(biāo)注方法的參數(shù)為準(zhǔn) 
  13.     */ 
  14.    @AliasFor("value"
  15.    Class<?>[] classes() default {}; 
  16.  
  17.    /** 
  18.     * 以spring表達(dá)的方式計算事件監(jiān)聽是否需要觸發(fā) 
  19.     */ 
  20.    String condition() default ""
  21.  

通過上述屬性,我們可以發(fā)現(xiàn),相比起實現(xiàn)接口的方式創(chuàng)建事件監(jiān)聽器,用注解的方式靈活性更加大,不僅可以指定多個接受事件類型,還可以增加是否觸發(fā)的條件。

使用示例

  1. @EventListener 
  2. public void customListener1(MyEvent event) { 
  3.     System.out.println("接受事件customListener1"); 

相關(guān)源碼

EventListenerMethodProcessor

  1. /** 
  2.  * 檢測bean里面是否包含 @EventListener 
  3.  */ 
  4. private void processBean(final String beanName, final Class<?> targetType) { 
  5.    if (!this.nonAnnotatedClasses.contains(targetType) && 
  6.          !targetType.getName().startsWith("java") && 
  7.          !isSpringContainerClass(targetType)) { 
  8.  
  9.       Map<Method, EventListener> annotatedMethods = null
  10.       try { 
  11.          // 找到所有包含 @EventListener 的方法 
  12.          annotatedMethods = MethodIntrospector.selectMethods(targetType, 
  13.                (MethodIntrospector.MetadataLookup<EventListener>) method -> 
  14.                      AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class)); 
  15.       } 
  16.       catch (Throwable ex) { 
  17.          // An unresolvable type in a method signature, probably from a lazy bean - let's ignore it. 
  18.          if (logger.isDebugEnabled()) { 
  19.             logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex); 
  20.          } 
  21.       } 
  22.  
  23.       if (CollectionUtils.isEmpty(annotatedMethods)) { 
  24.          // 如果這個類一個包含 @EventListener 方法都沒有則緩存到 nonAnnotatedClasses 中,減少重復(fù)計算 
  25.          this.nonAnnotatedClasses.add(targetType); 
  26.          if (logger.isTraceEnabled()) { 
  27.             logger.trace("No @EventListener annotations found on bean class: " + targetType.getName()); 
  28.          } 
  29.       } 
  30.       else { 
  31.          // Non-empty set of methods 
  32.          ConfigurableApplicationContext context = this.applicationContext; 
  33.          Assert.state(context != null"No ApplicationContext set"); 
  34.          // 可以創(chuàng)建自定義 EventListenerFactory,如果不創(chuàng)建,默認(rèn)擁有 DefaultEventListenerFactory 
  35.          List<EventListenerFactory> factories = this.eventListenerFactories; 
  36.          Assert.state(factories != null"EventListenerFactory List not initialized"); 
  37.          for (Method method : annotatedMethods.keySet()) { 
  38.             for (EventListenerFactory factory : factories) { 
  39.                // 對于每一個方法遍歷所有的工廠,找到一個支持的工廠就進(jìn)入創(chuàng)建并完成遍歷 
  40.                if (factory.supportsMethod(method)) { 
  41.                   // 根據(jù)方法創(chuàng)建 applicationListener,并將 applicationListener 添加給容器 
  42.                   Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName)); 
  43.                   ApplicationListener<?> applicationListener = 
  44.                         factory.createApplicationListener(beanName, targetType, methodToUse); 
  45.                   if (applicationListener instanceof ApplicationListenerMethodAdapter) { 
  46.                      ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator); 
  47.                   } 
  48.                   context.addApplicationListener(applicationListener); 
  49.                   break; 
  50.                } 
  51.             } 
  52.          } 
  53.          if (logger.isDebugEnabled()) { 
  54.             logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" + 
  55.                   beanName + "': " + annotatedMethods); 
  56.          } 
  57.       } 
  58.    } 

EventListenerMethodProcessor的processBean方法中,會遍歷已經(jīng)注冊的所有的bean,找到包含有被 @EventListener 標(biāo)注的方法。這些方法會被遍歷已經(jīng)創(chuàng)建的 EventListenerFactory 找到合適的工廠來生成 applicationListener,并將 applicationListener 注冊到容器的事件監(jiān)聽器列表。

ApplicationListenerMethodAdapter

  1. /** 
  2.  * 解析時間監(jiān)聽器支持的事件類型 
  3.  */ 
  4. private static List<ResolvableType> resolveDeclaredEventTypes(Method method, @Nullable EventListener ann) { 
  5.    int count = method.getParameterCount(); 
  6.    if (count > 1) { 
  7.       // 如果方法本身參數(shù)超過1個,則直接拋出異常 
  8.       throw new IllegalStateException( 
  9.             "Maximum one parameter is allowed for event listener method: " + method); 
  10.    } 
  11.  
  12.    if (ann != null) { 
  13.       // 取出 注解中的 classes屬性 
  14.       Class<?>[] classes = ann.classes(); 
  15.       if (classes.length > 0) { 
  16.          // 如果classes屬性不為空,則解析classes屬性并返回作為事件解析類型 
  17.          List<ResolvableType> types = new ArrayList<>(classes.length); 
  18.          for (Class<?> eventType : classes) { 
  19.             types.add(ResolvableType.forClass(eventType)); 
  20.          } 
  21.          return types; 
  22.       } 
  23.    } 
  24.  
  25.    // 如果傳入的classes屬性為空,并且方法沒有參數(shù),也拋出異常 
  26.    if (count == 0) { 
  27.       throw new IllegalStateException( 
  28.             "Event parameter is mandatory for event listener method: " + method); 
  29.    } 
  30.    return Collections.singletonList(ResolvableType.forMethodParameter(method, 0)); 

ApplicationListenerMethodAdapter的resolveDeclaredEventTypes方法會解析@EventListener標(biāo)簽的classes屬性,然后根據(jù)這個屬性決定事件監(jiān)聽器的監(jiān)聽的事件類型。

如果方法參數(shù)個數(shù)超過1個,直接拋出異常。這是一個事件觸發(fā)以后,如果接受的方法參數(shù)個數(shù)大于1個,spring沒辦法給方法進(jìn)行傳參。

如果classes屬性為空,并且方法參數(shù)個數(shù)為0個,也拋出異常。這是因為spring無法推斷這個監(jiān)聽器需要支持什么類型的事件。

除去上面兩種情況,解析都是成功,同時classes屬性會優(yōu)先被選擇為監(jiān)聽的事件類型。

  1. private boolean shouldHandle(ApplicationEvent event, @Nullable Object[] args) { 
  2.    if (args == null) { 
  3.       return false
  4.    } 
  5.    String condition = getCondition(); 
  6.    if (StringUtils.hasText(condition)) { 
  7.      // 如果 condition 屬性不為空,則進(jìn)行spring表達(dá)式計算結(jié)果并返回 
  8.       Assert.notNull(this.evaluator, "EventExpressionEvaluator must not be null"); 
  9.       return this.evaluator.condition( 
  10.             condition, event, this.targetMethod, this.methodKey, args, this.applicationContext); 
  11.    } 
  12.    return true

ApplicationListenerMethodAdapter的shouldHandle方法會根據(jù)@EventListener標(biāo)簽的condition屬性判斷是否需要推送消息。

如果condition不為空,則使用spring表達(dá)式計算condition得到結(jié)果,結(jié)果為true的時候才推送事件。如果condition為空,則不判斷直接推送。

責(zé)任編輯:武曉燕 來源: 今日頭條
相關(guān)推薦

2023-04-10 11:00:00

注解Demo源碼

2022-02-20 07:28:13

Spring注解用法

2023-07-10 08:43:53

SpringIDEA

2022-02-19 07:41:36

Bean注解項目

2022-12-07 08:02:43

Spring流程IOC

2022-06-09 07:27:14

JavaSpring容器

2022-05-30 11:17:44

Spring容器配置

2019-09-09 06:30:06

Springboot程序員開發(fā)

2023-05-08 08:11:49

@Component使用場景時序圖

2020-12-20 10:02:17

ContextReactrender

2023-06-02 16:24:46

SpringBootSSM

2020-10-14 06:23:54

SpringBean實例化

2011-04-15 09:44:45

Spring

2009-06-15 17:48:32

Spring注解注入屬性

2021-08-27 07:38:21

AndroidDialogContext

2021-03-08 00:11:02

Spring注解開發(fā)

2021-03-11 11:14:39

鴻蒙HarmonyOS應(yīng)用

2022-06-07 07:58:45

SpringSpring AOP

2017-08-02 14:44:06

Spring Boot開發(fā)注解

2015-03-31 18:26:43

陌陌社交
點贊
收藏

51CTO技術(shù)棧公眾號