spring源码解析系列之事件驱动模型@EventListener

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

说到前面

本文转自“天河聊技术”微信公众号

本次主要介绍监听器的实例化过程源码解析。

 

正文

我们跟踪@EventListener源码可以发现,背后的实现是这个类EventListenerMethodProcessor,spring应用上下文启动的时候会加载这个类,我看下这个类

public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware {

   protected final Log logger = LogFactory.getLog(getClass());

   @Nullable
   private ConfigurableApplicationContext applicationContext;

   private final EventExpressionEvaluator evaluator = new EventExpressionEvaluator();

// 增加map的默认并发数,可以减少map的自动扩容次数,一定程度上会提高程序的性能
   private final Set> nonAnnotatedClasses = Collections.newSetFromMap(new ConcurrentHashMap<>(64));

这个类中依赖了spring配置上下文对象和表达式解析器对象。

找到这个类实现了父类ApplicationContextAware.setApplicationContext()这个方法,获取spring配置上下文对象。

找到这个方法的实现,所有的单例bean实例化之后会执行这个方法

@Override
   public void afterSingletonsInstantiated() {//所有的单例bean创建完成后执行这个方法
//    下面开始创建ApplicationListener,获得创建ApplicationListener的工厂集合
      List factories = getEventListenerFactories();
//    获得配置上下文对象
      ConfigurableApplicationContext context = getApplicationContext();
//    获得bean的名字
      String[] beanNames = context.getBeanNamesForType(Object.class);
      for (String beanName : beanNames) {
         if (!ScopedProxyUtils.isScopedTarget(beanName)) {
            Class type = null;
            try {
//             获取bean的初始目标类的类型
               type = AutoProxyUtils.determineTargetClass(context.getBeanFactory(), 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) {
//             type表示的类或接口的超类或超接口是否和ScopedObject一样
               if (ScopedObject.class.isAssignableFrom(type)) {
                  try {
                     Class targetClass = AutoProxyUtils.determineTargetClass(
                           context.getBeanFactory(), 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 {
                  processBean(factories, beanName, type);
               }
               catch (Throwable ex) {
                  throw new BeanInitializationException("Failed to process @EventListener " +
                        "annotation on bean with name '" + beanName + "'", ex);
               }
            }
         }
      }
   }

重点看下这行代码,实例化监听器的操作在这里

try {
   processBean(factories, beanName, type);
}
protected void processBean(
         final List factories, final String beanName, final Class targetType) {

// 如果目标对象不是注解类型
      if (!this.nonAnnotatedClasses.contains(targetType)) {
         Map annotatedMethods = null;
         try {
//          找到加了@EventListener这个注解的方法
            annotatedMethods = MethodIntrospector.selectMethods(targetType,
                  (MethodIntrospector.MetadataLookup) 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 = getApplicationContext();
            for (Method method : annotatedMethods.keySet()) {
               for (EventListenerFactory factory : factories) {
                  if (factory.supportsMethod(method)) {
//                   获取可调用的方法
                     Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
//                   创建applicationListener对象,返回的是GenericApplicationListener的adaptor ApplicationListenerMethodAdapter对象
                     ApplicationListener applicationListener =
                           factory.createApplicationListener(beanName, targetType, methodToUse);
                     if (applicationListener instanceof ApplicationListenerMethodAdapter) {
//                      如果applicationListenr的具体类型是ApplicationListenerMethodAdapter,就进行初始化
                        ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
                     }
//                   如果applicationListenr的具体类型是ApplicationListenerMethodTransactionalAdapter,把这个监听器配置到spring配置上下文中
                     context.addApplicationListener(applicationListener);
                     break;
                  }
               }
            }
            if (logger.isDebugEnabled()) {
               logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
                     beanName + "': " + annotatedMethods);
            }
         }
      }
   }

看下这行代码的背后实现

如果applicationListenr的具体类型是ApplicationListenerMethodTransactionalAdapter,把这个监听器配置到spring配置上下文中,这个监听器类型是支持事务的监听器,在spring-tx包源码解析中会具体解析
                     context.addApplicationListener(applicationListener);
@Override
   public void addApplicationListener(ApplicationListener listener) {
      Assert.notNull(listener, "ApplicationListener must not be null");
      if (this.applicationEventMulticaster != null) {
//       如果事件发布管理器不为空,就把这个监听器添加到其中
         this.applicationEventMulticaster.addApplicationListener(listener);
      }
      else {
//       把监听器发布到spring上下文中
         this.applicationListeners.add(listener);
      }
   }

创建完applicationListener的adaptor对象后,注入到事件发布管理器中或者spring上下文中。

 

说到最后

本次介绍就这些,下次介绍基于spring的事件驱动模型发布一个事件的源码解析。

转载于:https://my.oschina.net/u/3775437/blog/1802436

你可能感兴趣的:(spring源码解析系列之事件驱动模型@EventListener)