5 Spring ApplicationListener 扩展版

ApplicationListener系列文章

  1. ApplicationListener 基础版

  2. ApplicationListener 进阶版

  3. ApplicationListener源码版

  4. ApplicationListener 问题版

  5. ApplicationListener 扩展版

  6. ApplicationListener 总结版

EventListener

前面通过实现ApplicationListener,就可以创建一个监听了,但是还是相对麻烦,因为一般我们是把监听和业务处理分开,能不能直接把监听器注解到业务方法中?EventListener就实现了这种方法。

使用范例

业务类的方法上直接添加相关的注解即可。

public class OrgServiceImpl {
    @EventListener
    public void add(OrgChangeEvent event){
        System.out.println("org event listener "+event.getSource().toString());
    }
}

上述通过: @EventListener,就创建了一个监听OrgChangeEvent的监听器。

注解解析

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EventListener {

   /**
    * Alias for {@link #classes}.
    */
   @AliasFor("classes")
   Class<?>[] value() default {};

   /**
    * The event classes that this listener handles.
    * <p>If this attribute is specified with a single value, the
    * annotated method may optionally accept a single parameter.
    * However, if this attribute is specified with multiple values,
    * the annotated method must <em>not</em> declare any parameters.
    */
   @AliasFor("value")
   Class<?>[] classes() default {};

   
   String condition() default "";

}

可以针对多个事件进行注解,例如:@EventListener({OrgChangeEvent.class, UserChangeEvent.class})

原理

常见的方式,普通创建一个监听,需要实现ApplicationListener接口,那么EventListener注解又如何实现的?

Processing of @EventListener annotations is performed via the internal EventListenerMethodProcessor bean which gets registered automatically when using Java config or manually via the <context:annotation-config/> or <context:component-scan/> element when using XML config.

上述EventLIstener注解的说明,发现了EventListenerMethodProcessor来实现EventListener的执行的。

EventListenerMethodProcessor

EventListenerMethodProcessor实现了三个接口:SmartInitializingSingleton(Bean对象初始化完成的后置对象), ApplicationContextAware(获取ApplicationContext), BeanFactoryPostProcessor(BeanFactory的后置处理器)。按照执行顺序,ApplicationContextAware>BeanFactoryPostProcessor>SmartInitializingSignleton。其中ApplicationContextAware都熟悉,可以直接忽略。

BeanFactroyPostProcessor

获取eventListenerFactories对象,整个Spring默认的实现对象就一个:DefaultEventListenerFactory

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   this.beanFactory = beanFactory;

   Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
   List<EventListenerFactory> factories = new ArrayList<>(beans.values());
   AnnotationAwareOrderComparator.sort(factories);
   this.eventListenerFactories = factories;
}
DefaultEventListenerFactory

EventListenerFactory主要是创建ApplicationListener,看看DefaultEventListenerFactory的源码

public class DefaultEventListenerFactory implements EventListenerFactory, Ordered {

   private int order = LOWEST_PRECEDENCE;


   public void setOrder(int order) {
      this.order = order;
   }

   @Override
   public int getOrder() {
      return this.order;
   }


   @Override
   public boolean supportsMethod(Method method) {
      return true;
   }

   @Override
   public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {
      //核心:创建ApplicationListener,ApplicationListenerMethodAdapter适配器
      return new ApplicationListenerMethodAdapter(beanName, type, method);
   }

}

SmartInitializingSingleton

SmartInitializingSignLeton的调用时机:AbstractApplicationContext.refresh(finishBeanFactoryInitialization->preInstantiateSingletons),初始化所有的非延迟加载的单例对象后,针对所有初始化完成的Bean,如果该Bean是SmartInitializingSingleton实现类,会单独调用afterSingletonsInstantiated方法。

@Override
public void afterSingletonsInstantiated() {
   ConfigurableListableBeanFactory beanFactory = this.beanFactory;
   Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
   //获取所有的Bean
   String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
   for (String beanName : beanNames) {
      if (!ScopedProxyUtils.isScopedTarget(beanName)) {
         Class<?> type = null;
         try {
            type = AutoProxyUtils.determineTargetClass(beanFactory, beanName);
         }
         catch (Throwable ex) {
            // An unresolvable bean type, probably from a lazy bean - let's ignore it.
            if (logger.isDebugEnabled()) {
               logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
            }
         }
         if (type != null) {
            if (ScopedObject.class.isAssignableFrom(type)) {
               try {
                  Class<?> targetClass = AutoProxyUtils.determineTargetClass(
                        beanFactory, ScopedProxyUtils.getTargetBeanName(beanName));
                  if (targetClass != null) {
                     type = targetClass;
                  }
               }
               catch (Throwable ex) {
                  // An invalid scoped proxy arrangement - let's ignore it.
                  if (logger.isDebugEnabled()) {
                     logger.debug("Could not resolve target bean for scoped proxy '" + beanName + "'", ex);
                  }
               }
            }
            try {
               //核心,处理Bean
               processBean(beanName, type);
            }
            catch (Throwable ex) {
               throw new BeanInitializationException("Failed to process @EventListener " +
                     "annotation on bean with name '" + beanName + "'", ex);
            }
         }
      }
   }
}

获取到符合条件的Bean对象,开始处理。

private void processBean(final String beanName, final Class<?> targetType) {
   //
   if (!this.nonAnnotatedClasses.contains(targetType) &&
         //判断当前类是否具有EventListener注解,无论是方法还是字段,EventListener只支持方法和注解。
         AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
         !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 - let's ignore it.
         if (logger.isDebugEnabled()) {
            logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
         }
      }
      
      if (CollectionUtils.isEmpty(annotatedMethods)) {
         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");
         List<EventListenerFactory> factories = this.eventListenerFactories;
         Assert.state(factories != null, "EventListenerFactory List not initialized");
         for (Method method : annotatedMethods.keySet()) {
            for (EventListenerFactory factory : factories) {
               //EventListenerFactory的钩子方法
               if (factory.supportsMethod(method)) {
                  //获取方法,如果当前类没有,就获取接口的方法
                  Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
                  //根据Bean的名称和对应的Method,调用工厂,创建监听对象,其实就是适配器监听
                  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);
         }
      }
   }
}

ApplicationListenerMethodAdapter

EventListener最终转化为ApplicationListenerMethodAdapter,ApplicationListenerMethodAdapter的结构如下:

在这里插入图片描述

因此,我们只需要看看ApplicationListenerMethodAdapter的onApplicationEvent如何处理事件的。

public void onApplicationEvent(ApplicationEvent event) {
   processEvent(event);
}

public void processEvent(ApplicationEvent event) {
   //组装方法执行时的参数
   Object[] args = resolveArguments(event);
   if (shouldHandle(event, args)) {
      //执行方法
      Object result = doInvoke(args);
      if (result != null) {
         //有意思的地方,如果返回值非null,并且是普通数据,
         //例如:基本数据格式,竟然还会包装成PayloadApplicationEvent,再次发送一次事件
         handleResult(result);
      }
      else {
         logger.trace("No result object given - no result to handle");
      }
   }
}

@Nullable
protected Object doInvoke(Object... args) {
   Object bean = getTargetBean();
   // Detect package-protected NullBean instance through equals(null) check
   if (bean.equals(null)) {
      return null;
   }

   ReflectionUtils.makeAccessible(this.method);
   try {
      //反射相关可以忽略
      return this.method.invoke(bean, args);
   }
   catch (IllegalArgumentException ex) {
      assertTargetBean(this.method, bean, args);
      throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex);
   }
   catch (IllegalAccessException ex) {
      throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex);
   }
   catch (InvocationTargetException ex) {
      // Throw underlying exception
      Throwable targetException = ex.getTargetException();
      if (targetException instanceof RuntimeException) {
         throw (RuntimeException) targetException;
      }
      else {
         String msg = getInvocationErrorMessage(bean, "Failed to invoke event listener method", args);
         throw new UndeclaredThrowableException(targetException, msg);
      }
   }
}

思考

通过EventLitener的实现方式,其实后续也可以实现方法级别的注解,具体操作步骤如下:

  1. 通过SmartInitializingSignLeton的afterSingletonsInstantiated方法,获取所有Bean中带有指定注解的方法。

  2. 针对对象的特定方法生成相关的适配器对象,这样就可以正常的调用该对象的方法。

通过持有对象+方法,生成适配器对象。

其实相关的实践有很多,可以在SpringBoot中,搜索:SmartInitializingSignLeton的实现类,会发现很多能力都是通过上述方式实现。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值