ApplicationListener是Spring事件機制的一部分,與抽象類ApplicationEvent類配合來完成ApplicationContext的事件機制。java
若是容器中存在ApplicationListener的Bean,當ApplicationContext調用publishEvent方法時,對應的Bean會被觸發。這一過程是典型的觀察者模式的實現。spring
源碼:app
@FunctionalInterface public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { /** * Handle an application event. * @param event the event to respond to */ void onApplicationEvent(E event); }
以Spring的內置事件ContextRefreshedEvent爲例,當ApplicationContext被初始化或刷新時,會觸發ContextRefreshedEvent事件,下面咱們就實現一個ApplicationListener來監聽此事件的發生。ide
@Component // 需對該類進行Bean的實例化 public class LearnListener implements ApplicationListener<ContextRefreshedEvent> { @Override public void onApplicationEvent(ContextRefreshedEvent event) { // 打印容器中出事Bean的數量 System.out.println("監聽器得到容器中初始化Bean數量:" + event.getApplicationContext().getBeanDefinitionCount()); } }
在容器建立完成後,在finishRefresh()方法中發佈了一個事件——ContextRefreshedEventpost
咱們來具體看一下這個事件是如何發佈的this
protected void publishEvent(Object event, @Nullable ResolvableType eventType) { Assert.notNull(event, "Event must not be null"); // Decorate event as an ApplicationEvent if necessary ApplicationEvent applicationEvent; if (event instanceof ApplicationEvent) { applicationEvent = (ApplicationEvent) event; } else { applicationEvent = new PayloadApplicationEvent<>(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); } } }
派發事件:getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);3d
這裏的執行invokeListener主要是來回調listener的接口方法code
以上就是spring中事件發佈的流程。blog
在事件發佈的過程當中,有一步是獲取事件的派發器,那麼事件派發器是在哪裏建立的呢?接口
實際上在容器初始化時,執行了initApplicationEventMulticaster()這個方法,來爲容器初始化事件派發器。
protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); //先來判斷容器中有沒有applicationEventMulticaster if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isTraceEnabled()) { logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { //若是沒有則建立一個派發器 this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isTraceEnabled()) { logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " + "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]"); } } }
APPLICATION_EVENT_MULTICASTER_BEAN_NAME:
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
refresh()方法中執行了registerListeners()來給容器中註冊監聽器
protected void registerListeners() { // Register statically specified listeners first. 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! //根據類型獲取全部的監聽器的Bean名稱 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); } } }
除了實現ApplicationListener接口來完成事件監聽之外,@EventListener這個註解也一樣能夠監聽事件的發生
只須要將@EventListener標註在方法上面:
@EventListener(classes = {ApplicationEvent.class}) public void listen(ApplicationEvent applicationEvent){ System.out.println("監聽到:"+applicationEvent); }