Spring的事件监听ApplicationListener接口

九、ApplicationListener接口

ApplicationListener接口是Spring提供的接口,基于事件发布机制实现的。实现该接口的同时会指定一个泛型,当发布的事件类型于实现ApplicationListener接口的bean的泛型一致时,会回调这个bean的监听方法,并且把事件传递过去。

我们也可以仿造发布事件的源码,自己手动使用ApplicationContext发布事件,那么同样也会触发,监听器的回调。

@Component
public class SysApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    
    
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
    
    
        // 这里可以使用传递过来的事件参数, 来获得ApplicationContext
        // 因此可以考虑在此处开启一些任务。比如缓存初始化, 读取定时任务, 开启线程任务等。
        // 因为这个时候, Spring容器已经初始化好了, 并且还能获取到ApplicationContext。
        ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();
		System.out.println("==============Spring容器刷新完毕, 应用启动成功!!!==============");
    }
}

原理剖析:

// 同样的,我们来到AbstractApplicationContext的refresh方法, 我们只看finishRefresh();
public class AbstractApplicationContext{
    
    
    synchronized (this.startupShutdownMonitor) {
    
    
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory); <<------//往BeanFactory中放了ApplicationListenerDetector对象
                                                     // 并且把当前对象ApplicationContext传进去了
			try {
    
    
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();   <<----------------// 初始化事件发布的多播器 

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();  <<----------------------------// 注册监听器

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();   <<------------------------------// 发布对应的事件
			}

			catch (BeansException ex) {
    
    
				if (logger.isWarnEnabled()) {
    
    
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
    
    
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
}
// 进入finishRefresh()方法
protected void finishRefresh() {
    
    
    // Initialize lifecycle processor for this context.
    initLifecycleProcessor();

    // Propagate refresh to lifecycle processor first.
    getLifecycleProcessor().onRefresh();

    // Publish the final event.
    publishEvent(new ContextRefreshedEvent(this));   // 发布ContextRefreshEvent事件, 注意this代表当前对象
                                                     //       即, 这个事件对象包装了ApplicationContext
    												 // 显然, ApplicationContext持有多播器这个对象,发布事件
                                                     //       是使用持有的多播器来完成的
                                                     // 从这里也可以看出, 我们也可以自己手动使用
    												 //     applicationContext对象, 来发布事件,
                                                     //     也将会触发下面这个方法的调用

    // Participate in LiveBeansView MBean, if active.
    LiveBeansView.registerApplicationContext(this);
}
// 具体发布的方法publishEvent, 第二个参数是null
protected void publishEvent(Object event, ResolvableType eventType) {
    
    
   Assert.notNull(event, "Event must not be null");
   if (logger.isTraceEnabled()) {
    
    
      logger.trace("Publishing event in " + getDisplayName() + ": " + event);
   }

   // Decorate event as an ApplicationEvent if necessary
   ApplicationEvent applicationEvent;
   if (event instanceof ApplicationEvent) {
    
    
      applicationEvent = (ApplicationEvent) event;
   }
   else {
    
    
      applicationEvent = new PayloadApplicationEvent<Object>(this, event);
      if (eventType == null) {
    
    
         eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
      }
   }

   // Multicast right now if possible - or lazily once the multicaster is initialized
   if (this.earlyApplicationEvents != null) {
    
    
      this.earlyApplicationEvents.add(applicationEvent); // 多播器初始化后再发布
   }
   else {
    
    
      getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); // 立即发布(默认)
   }

   // Publish event via parent context as well... // 同样的, 通知父容器发布该事件
   if (this.parent != null) {
    
    
      if (this.parent instanceof AbstractApplicationContext) {
    
    
         ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
      }
      else {
    
    
         this.parent.publishEvent(event); // 从这里又重写调用了本方法,
      }
   }
}
// 好的, 我们来到多播器的源码SimpleApplicationEventMulticaster,
//       注意到SimpleApplicationEventMulticaster继承自AbstractApplicationEventMulticaster,
//       而AbstractApplicationEventMulticaster实现了BeanFactoryAware接口, 所以多播器能够拿到beanFactory,
//       进而能从bean工厂中拿到所有的监听器, 也就是实现了ApplicationListener接口的bean
public class SimpleApplicationEventMulticaster{
    
    
    @Override
    public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
    
    
        // 这里在解析事件的类型
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        // 那么这里还存留着一个问题, 多播器是怎么拿到spring容器中所有的监听器的, 在后面我们来看看
        for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
    
    
            Executor executor = getTaskExecutor(); 
            if (executor != null) {
    
    
                executor.execute(new Runnable() {
    
    
                    @Override
                    public void run() {
    
    
                        invokeListener(listener, event);  // ??多线程
                    }
                });
            }
            else {
    
    
                invokeListener(listener, event); // 回调监听器, 下面具体看看这个方法是怎么回调的
            }
        }
    }
}
public class SimpleApplicationEventMulticaster{
    
    
    protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
    
    
       ErrorHandler errorHandler = getErrorHandler();
       if (errorHandler != null) {
    
    
          try {
    
    
             doInvokeListener(listener, event);
          }
          catch (Throwable err) {
    
    
             errorHandler.handleError(err);
          }
       }
       else {
    
    
          doInvokeListener(listener, event); // 好的, 继续调用
       }
    }
}
public class SimpleApplicationEventMulticaster{
    
    
    private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
    
    
       try {
    
    
          listener.onApplicationEvent(event); // 终于看到了, 这里在回调监听器重写的onApplicationEvent方法!!!
       }
       catch (ClassCastException ex) {
    
    
          String msg = ex.getMessage();
          if (msg == null || msg.startsWith(event.getClass().getName())) {
    
    
             // Possibly a lambda-defined listener which we 
             // could not resolve the generic event type for
             Log logger = LogFactory.getLog(getClass());
             if (logger.isDebugEnabled()) {
    
    
                logger.debug("Non-matching event type for listener: " + listener, ex);
             }
          }
          else {
    
    
             throw ex;
          }
       }
    }
// 好的,到了这里, 我们来看看这个方法是怎么拿到所有的监听器的 getApplicationListeners

protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, 
                                                                     ResolvableType eventType) 
{
    
    

		Object source = event.getSource();
		Class<?> sourceType = (source != null ? source.getClass() : null);
		ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

		// Quick check for existing entry on ConcurrentHashMap...
		ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
		if (retriever != null) {
    
    
			return retriever.getApplicationListeners();
		}

		if (this.beanClassLoader == null ||
				(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) 
                 &&(sourceType == null || 
                    ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) 
        {
    
    
			// Fully synchronized building and caching of a ListenerRetriever
			synchronized (this.retrievalMutex) {
    
    
				retriever = this.retrieverCache.get(cacheKey);
				if (retriever != null) {
    
    
					return retriever.getApplicationListeners();
				}
                
                // 前面似乎是在做一些缓存之类的, 重点看这里, retrieveApplicationListeners这里查询所有的监听器
				retriever = new ListenerRetriever(true);
				Collection<ApplicationListener<?>> listeners =
						retrieveApplicationListeners(eventType, sourceType, retriever);
				this.retrieverCache.put(cacheKey, retriever);
				return listeners;
			}
		}
		else {
    
    
			// No ListenerRetriever caching -> no synchronization necessary
			return retrieveApplicationListeners(eventType, sourceType, null);
		}
	}
private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, 
                                                                        Class<?> sourceType,
                                                                        ListenerRetriever retriever) 
{
    
    

   LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>();
    // 监听器分成下面 2 部分来玩, 这两部分都被当前多播器的defaultRetriever属性对象持有,所属类是多播器的私有内部类
   Set<ApplicationListener<?>> listeners;
   Set<String> listenerBeans;
    
   synchronized (this.retrievalMutex) {
    
    
      listeners = 
          // 这里在拿到多播器中的defaultRetriever的属性中的applicationListener
          // 那么问题来了:首先知道defaultRetriever是多播器SimpleApplicationEventMulticaster中的私有内部类, 
          // applicationListenerBeans和applicationListeners是这个私有类的public属性。
          // 那么这个监听器是怎样加入到defaultRetriever这个对象当中去的呢?
          new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners);
      listenerBeans = 
          new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans);
   }
   for (ApplicationListener<?> listener : listeners) {
    
    
       // 判断监听器是否支持监听当前传过来的事件, 即发布这个事件, 监听器要不要被回调
      if (supportsEvent(listener, eventType, sourceType)) {
    
    
         if (retriever != null) {
    
    
            retriever.applicationListeners.add(listener);
         }
         allListeners.add(listener);
      }
   }
   if (!listenerBeans.isEmpty()) {
    
    
      BeanFactory beanFactory = getBeanFactory();
      for (String listenerBeanName : listenerBeans) {
    
    
         try {
    
    
            Class<?> listenerType = beanFactory.getType(listenerBeanName);
             // 这里也在判断支不支持当前传过来的这个事件
            if (listenerType == null || supportsEvent(listenerType, eventType)) {
    
    
                // 调用了getBean方法了
               ApplicationListener<?> listener =
                     beanFactory.getBean(listenerBeanName, ApplicationListener.class);
               if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) 
               {
    
    
                  if (retriever != null) {
    
    
                      // 加入到上面这种情况中去了
                     retriever.applicationListenerBeans.add(listenerBeanName);
                  }
                  allListeners.add(listener);
               }
            }
         }
         catch (NoSuchBeanDefinitionException ex) {
    
    
            // Singleton listener instance (without backing bean definition) disappeared -
            // probably in the middle of the destruction phase
         }
      }
   }
    // 给监听器排序
    AnnotationAwareOrderComparator.sort(allListeners);
    if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
    
    
        retriever.applicationListeners.clear();
        retriever.applicationListeners.addAll(allListeners);
    }
   return allListeners;
}
// 我们可以看到AbstractApplicationContext的refresh方法中的调用的registerListener方法
public abstract class AbstractApplicationContext
    protected void registerListeners() {
    
    
        // Register statically specified listeners first.
        // 获取到所有的监听器, 并且把它加入到多播器中的私有内部类对象defaultRetriever中去
        // 这个getApplicationListener()方法可以获取到ApplicationContext的ApplicationListener的集合,
        // 那么这个监听器的集合是什么时候添加进去的呢?我们可以看下ApplicationListenerDetector这个类,
        // 它实现类BeanPostProcessor接口, 在识别bean实现了ApplicationListener接口的话, 
        // 就把它放到ApplicationContext的监听器集合里面去, 源码在下面
        // 但是这里需要注意的是: 这个registerListeners方法现在调用时, beanFactory还没开始与初始化过程, 
        //                    所以这里还是没有拿到我们配置的的ApplicationListener, 真正拿到是在下面
        for (ApplicationListener<?> listener : getApplicationListeners()) {
    
    
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let post-processors apply to them!
        // 这里才是拿到了ApplicationListener接口实现类的bean的名字, 注意: 这个时候beanFactory还未预初始化
		// 这里可以拿到我们配置的实现了Application接口的实现类的名字了, 并且也把它给到了defaultRetriever中
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
    
    
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }

        // Publish early application events now that we finally have a multicaster...
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
    
    
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
    
    
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }
}
class AbstractApplicationEventMulticaster{
    
    
	@Override
    public void addApplicationListener(ApplicationListener<?> listener) {
    
    
       synchronized (this.retrievalMutex) {
    
    
          // Explicitly remove target for a proxy, if registered already,
          // in order to avoid double invocations of the same listener.
          Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
          if (singletonTarget instanceof ApplicationListener) {
    
    
             this.defaultRetriever.applicationListeners.remove(singletonTarget);
          }
           // 添加到retriever的applicationListeners属性
          this.defaultRetriever.applicationListeners.add(listener); 
          this.retrieverCache.clear();
       }
    }
    
    @Override
	public void addApplicationListenerBean(String listenerBeanName) {
    
    
		synchronized (this.retrievalMutex) {
    
    
            // 添加到retrivever的applicationListenerBeans属性, 这个才是关键, 我们自己配置的在这里设置进去了
			this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
			this.retrieverCache.clear();
		}
	}
}
public class ApplicationListenerDetector{
    
    
    
    // 虽然ApplicationListenerDetector并没有实现BeanFactoryAware接口,但是这里它有了ApplicationContext属性
    private transient final AbstractApplicationContext applicationContext;
    
    @Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
    
    
        // 判断是否实现了ApplicationListener接口
		if (this.applicationContext != null && bean instanceof ApplicationListener) {
    
    
			// potentially not detected as a listener by getBeanNamesForType retrieval
			Boolean flag = this.singletonNames.get(beanName);
			if (Boolean.TRUE.equals(flag)) {
    
    
				// singleton bean (top-level or inner): register on the fly
                // 添加到ApplicationContext中去, 
                // 那么问题又来了, applicationContext属性是怎样给到这个类的?
                // 答案是在refresh方法中的prepareBeanFactory(beanFactory);方法中传进去了
				this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
			}
			else if (Boolean.FALSE.equals(flag)) {
    
    
				if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
    
    
					// inner bean with other scope - can't reliably process events
					logger.warn("Inner bean '" + beanName 
                                + "' implements ApplicationListener interface "
                                + "but is not reachable for event multicasting by its containing 
                                ApplicationContext " + "because it does not have singleton scope. Only 
                                top-level listener beans are allowed " +"to be of non-singleton 
                                scope.");
				}
				this.singletonNames.remove(beanName);
			}
		}
		return bean;
	}
}
// 还有一点 多播器的抽象父类AbstractApplicationEventMulticaster实现了BeanFactoryWare接口, 
// 重写的setBeanFactory方法会被回调。那么问题又来了, 为什么这个方法会被回调呢?
// 或者说多播器是因为加入了spring容器作为bean被回调, 还是代码手动回调的呢?
// 答案是手动回调的,我们可以看看多播器初始化的代码。

public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, 
                                                          BeanClassLoaderAware, BeanFactoryAware 
{
    
    
    // 默认初始化了私有的内部类(私有内部类:外界不可以访问, 外部类可以访问私有内部类中的public属性和方法)
	private final ListenerRetriever defaultRetriever = new ListenerRetriever(false); 
    private Object retrievalMutex = this.defaultRetriever;                                                 
    @Override
	public void setBeanFactory(BeanFactory beanFactory) {
    
     
		this.beanFactory = beanFactory;
		if (beanFactory instanceof ConfigurableBeanFactory) {
    
    
			ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;
			if (this.beanClassLoader == null) {
    
    
				this.beanClassLoader = cbf.getBeanClassLoader();
			}
             // cbf.getSingletonMutex()返回的就是singletonObjects【spring容器保存单例bean的地方】
			this.retrievalMutex = cbf.getSingletonMutex();
		}
	}
                                                        
}

// 我们看下refresh()方法调用了initApplicationEventMulticaster()这个方法
class AbstractApplicationContext{
    
    
	protected void initApplicationEventMulticaster() {
    
    
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    	// 这里先看容器里面有没有名字叫做'applicationEventMulticaster'的bean。
    	// 需要注意的是: 我们配置的bean, 此时在beanFactory中还只是BeanDefinition, 
        //             还没有开始bean创建的预初始化过程。
        //             getBean方法会先从singleObjects中找, 找不到的话, 会找beanDefintion, 从而完成初始化的过程
		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
    
    
            // 再从容器里面拿ApplicationEventMulticaster接口的实现类, 名字是'applicationEventMulticaster'
			this.applicationEventMulticaster =
					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, 
                                        ApplicationEventMulticaster.class);
			if (logger.isDebugEnabled()) {
    
    
				logger.debug("Using ApplicationEventMulticaster ["
                             + this.applicationEventMulticaster + "]");
			}
		}
		else {
    
    
            // 在这里, 看到是手动创建的多播器, 并且把beanFactory传了进去, 在这里继续跟进
			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, 
                                          this.applicationEventMulticaster);
			if (logger.isDebugEnabled()) {
    
    
				logger.debug("Unable to locate ApplicationEventMulticaster with name '" 
                             +APPLICATION_EVENT_MULTICASTER_BEAN_NAME 
                             +"': using default [" + this.applicationEventMulticaster + "]");
			}
		}
	}
}
class SimpleApplicationEventMulticaster{
    
    
    /**
     * Create a new SimpleApplicationEventMulticaster for the given BeanFactory.
     */
    public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
    
    
       // 在构造方法里面调用了setBeanFactory, 这个方法在父类里面, 重写的BeanFactory接口的方法被调用了
       setBeanFactory(beanFactory);
    }
}
public abstract class AbstractApplicationEventMulticaster{
    
    
	@Override
	public void setBeanFactory(BeanFactory beanFactory) {
    
     // 好的, 也就是这个方法被调用了
		this.beanFactory = beanFactory;
		if (beanFactory instanceof ConfigurableBeanFactory) {
    
    
			ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;
			if (this.beanClassLoader == null) {
    
    
				this.beanClassLoader = cbf.getBeanClassLoader();
			}
			this.retrievalMutex = cbf.getSingletonMutex();
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_16992475/article/details/119901751