人工智能

Spring-Context注解源码之@EventListener

时间:2010-12-5 17:23:32  作者:人工智能   来源:IT科技  查看:  评论:0
内容摘要:注解说明Annotation that marks a method as a listener for application events.以注解的方式将一个方法标记为事件监听器。如果对于spri

 注解说明

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

以注解的解源方式将一个方法标记为事件监听器。如果对于spring事件监听机制还不了解的解源小伙伴点击查看一文彻底搞懂spring事件监听机制

属性说明

public @interface EventListener {     /**     * 同class     */    @AliasFor("classes")    Class<?>[] value() default { };    /**     * 监听事件的类型     * 如果这个属性长度不为空,则以这个属性的解源为准     * 如果这个属性长度为空,则以被标注方法的解源参数为准     */    @AliasFor("value")    Class<?>[] classes() default { };    /**     * 以spring表达的方式计算事件监听是否需要触发     */    String condition() default ""; } 

通过上述属性,我们可以发现,解源相比起实现接口的解源方式创建事件监听器,用注解的解源方式灵活性更加大,不仅可以指定多个接受事件类型,解源还可以增加是解源否触发的条件。

使用示例

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

相关源码

EventListenerMethodProcessor

/**  * 检测bean里面是解源否包含 @EventListener  */ private void processBean(final String beanName, final Class<?> targetType) {     if (!this.nonAnnotatedClasses.contains(targetType) &&          !targetType.getName().startsWith("java") &&          !isSpringContainerClass(targetType)) {        Map<Method, EventListener> annotatedMethods = null;       try {           // 找到所有包含 @EventListener 的方法          annotatedMethods = MethodIntrospector.selectMethods(targetType,                (MethodIntrospector.MetadataLookup<EventListener>) method ->                      AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));       }       catch (Throwable ex) {           // An unresolvable type in a method signature, probably from a lazy bean - lets ignore it.          if (logger.isDebugEnabled()) {              logger.debug("Could not resolve methods for bean with name " + beanName + "", ex);          }       }       if (CollectionUtils.isEmpty(annotatedMethods)) {           // 如果这个类一个包含 @EventListener 方法都没有则缓存到 nonAnnotatedClasses 中,减少重复计算          this.nonAnnotatedClasses.add(targetType);          if (logger.isTraceEnabled()) {              logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());          }       }       else {           // Non-empty set of methods          ConfigurableApplicationContext context = this.applicationContext;          Assert.state(context != null,解源 "No ApplicationContext set");          // 可以创建自定义 EventListenerFactory,如果不创建,解源默认拥有 DefaultEventListenerFactory          List<EventListenerFactory> factories = this.eventListenerFactories;          Assert.state(factories != null,解源 "EventListenerFactory List not initialized");          for (Method method : annotatedMethods.keySet()) {              for (EventListenerFactory factory : factories) {                 // 对于每一个方法遍历所有的工厂,找到一个支持的解源工厂就进入创建并完成遍历                if (factory.supportsMethod(method)) {                    // 根据方法创建 applicationListener,站群服务器并将 applicationListener 添加给容器                   Method methodToUse = AopUtils.selectInvocableMethod(method,解源 context.getType(beanName));                   ApplicationListener<?> applicationListener =                         factory.createApplicationListener(beanName, targetType, methodToUse);                   if (applicationListener instanceof ApplicationListenerMethodAdapter) {                       ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);                   }                   context.addApplicationListener(applicationListener);                   break;                }             }          }          if (logger.isDebugEnabled()) {              logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean " +                   beanName + ": " + annotatedMethods);          }       }    } } 

EventListenerMethodProcessor的processBean方法中,会遍历已经注册的所有的bean,找到包含有被 @EventListener 标注的方法。这些方法会被遍历已经创建的 EventListenerFactory 找到合适的工厂来生成 applicationListener,并将 applicationListener 注册到容器的事件监听器列表。

ApplicationListenerMethodAdapter

/**  * 解析时间监听器支持的事件类型  */ private static List<ResolvableType> resolveDeclaredEventTypes(Method method, @Nullable EventListener ann) {     int count = method.getParameterCount();    if (count > 1) {        // 如果方法本身参数超过1个,则直接抛出异常       throw new IllegalStateException(             "Maximum one parameter is allowed for event listener method: " + method);    }    if (ann != null) {        // 取出 注解中的 classes属性       Class<?>[] classes = ann.classes();       if (classes.length > 0) {           // 如果classes属性不为空,则解析classes属性并返回作为事件解析类型          List<ResolvableType> types = new ArrayList<>(classes.length);          for (Class<?> eventType : classes) {              types.add(ResolvableType.forClass(eventType));          }          return types;       }    }    // 如果传入的classes属性为空,并且方法没有参数,也抛出异常    if (count == 0) {        throw new IllegalStateException(             "Event parameter is mandatory for event listener method: " + method);    }    return Collections.singletonList(ResolvableType.forMethodParameter(method, 0)); } 

ApplicationListenerMethodAdapter的resolveDeclaredEventTypes方法会解析@EventListener标签的classes属性,然后根据这个属性决定事件监听器的监听的事件类型。

如果方法参数个数超过1个,直接抛出异常。这是云服务器一个事件触发以后,如果接受的方法参数个数大于1个,spring没办法给方法进行传参。

如果classes属性为空,并且方法参数个数为0个,也抛出异常。这是因为spring无法推断这个监听器需要支持什么类型的事件。

除去上面两种情况,解析都是成功,同时classes属性会优先被选择为监听的事件类型。

private boolean shouldHandle(ApplicationEvent event, @Nullable Object[] args) {     if (args == null) {        return false;    }    String condition = getCondition();    if (StringUtils.hasText(condition)) {       // 如果 condition 属性不为空,则进行spring表达式计算结果并返回       Assert.notNull(this.evaluator, "EventExpressionEvaluator must not be null");       return this.evaluator.condition(             condition, event, this.targetMethod, this.methodKey, args, this.applicationContext);    }    return true; } 

ApplicationListenerMethodAdapter的shouldHandle方法会根据@EventListener标签的condition属性判断是否需要推送消息。

如果condition不为空,则使用spring表达式计算condition得到结果,结果为true的时候才推送事件。如果condition为空,则不判断直接推送。

copyright © 2025 powered by 益强资讯全景  滇ICP备2023006006号-31sitemap