spring中的ApplicationListener是一個監聽器,用來監聽容器中發布的事件
監聽器也是一種觀察者設計模式,該接口有一個onApplicationEvent()方法,
在事件發布時,此方法將會調用,實現監聽的功能。
/** * Interface to be implemented by application event listeners. * Based on the standard {@code java.util.EventListener} interface * for the Observer design pattern. * * <p>As of Spring 3.0, an ApplicationListener can generically declare the event type * that it is interested in. When registered with a Spring ApplicationContext, events * will be filtered accordingly, with the listener getting invoked for matching event * objects only. * * @author Rod Johnson * @author Juergen Hoeller * @param <E> the specific ApplicationEvent subclass to listen to * @see org.springframework.context.event.ApplicationEventMulticaster */ public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { /** * Handle an application event. * @param event the event to respond to */ void onApplicationEvent(E event); }
自定義一個實現了ApplicationListener接口的實現類MyEventListener:
@Component public class MyEventListener implements ApplicationListener<ApplicationEvent>{ @Override public void onApplicationEvent(ApplicationEvent event) { System.out.println("監聽到的事件發布。。。。。。。。。。"+event); } }
配置類:
@Configuration @Import({MyEventListener.class}) public class ExtConfig { }
測試類:
public class ExtTest { @Test public void test(){ AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ExtConfig.class); applicationContext.publishEvent(new ApplicationEvent(new String("我發布的事件")) {}); applicationContext.close(); } }
打印結果:可以看到監聽到了容器中三個事件的發布
監聽到的事件發布。。。。。。。。。。org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@3339ad8e: org.springframework.context.annotation.AnnotationConfigApplicationContext doClose 監聽到的事件發布。。。。。。。。。。ExtTest$1[source=我發布的事件] 信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@3339ad8e: 監聽到的事件發布。。。。。。。。。。org.springframework.context.event.ContextClosedE
發布流程:
1》容器刷新完成事件ContextRefreshedEvent:
refresh()--》finishRefresh()--》publishEvent(new ContextRefreshedEvent(this));
2》自己發布的事件:
publishEvent(event, null);
3》容器關閉的事件ContextClosedEvent:
close()-》doClose()-》publishEvent(new ContextClosedEvent(this));
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); } } }
執行getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);獲取多波器(派發器)
multicastEvent(applicationEvent, eventType):
@Override public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
//獲取到所有的監聽器,並遍歷循環 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); } } }
執行:doInvokeListener(listener, event)--》listener.onApplicationEvent(event);
@SuppressWarnings({"unchecked", "rawtypes"}) private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) { try { listener.onApplicationEvent(event); } 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; } } }
最終會去調用具體的onApplicationEvent()方法;

getApplicationEventMulticaster()多播器(派發器)的獲取:
它是直接返回一個applicationEventMulticaster對象
ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException { if (this.applicationEventMulticaster == null) { throw new IllegalStateException("ApplicationEventMulticaster not initialized - " + "call 'refresh' before multicasting events via the context: " + this); } return this.applicationEventMulticaster; }
在finishRefresh()前,有一個initApplicationEventMulticaster()初始化多播器的操作。
// 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();
initApplicationEventMulticaster():
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
/** * Initialize the ApplicationEventMulticaster. * Uses SimpleApplicationEventMulticaster if none defined in the context. * @see org.springframework.context.event.SimpleApplicationEventMulticaster */ protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//先從beanFactory中判斷是否有該bean,如果有就直接從beanFacotry中獲取 if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isDebugEnabled()) { logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else {
//如果沒有就自己創建一個SimpleApplocationEventMulticaster對象,它是ApplicationEventMulticaster的子類型
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
//並注冊到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 + "]"); } } }
還有另外一種實現監聽機制的方法:使用@EventListener注解:
寫一個UserService
@Service public class UserService { @EventListener(classes = {ApplicationEvent.class}) public void listen(ApplicationEvent applicationEvent){ System.out.println("applicationEvent...監聽到的事件。。。"+applicationEvent); } }
打印結果:
UserService applicationEvent...監聽到的事件。。。org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@3339ad8e: startup date [Wed Dec 25 19:38:28 CST 2019]; root of context hierarchy] UserService applicationEvent...監聽到的事件。。。ExtTest$1[source=我發布的事件] UserService applicationEvent...監聽到的事件。。。org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@3339ad8e: startup date [Wed Dec 25 19:38:28 CST 2019]; root of context hierarchy]
EventListener 注解:
* @author Stephane Nicoll * @since 4.2 * @see EventListenerMethodProcessor */ @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface EventListener {
EventListenerMethodProcessor類:實現了SmartInitializingSingleton接口,並重寫了afterSingletonsInstantiated()方法:
public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware {
SmartInitializingSingleton 接口:它是在所有的bean實例都創建初始化后調用這個方法:
public interface SmartInitializingSingleton { /** * Invoked right at the end of the singleton pre-instantiation phase, * with a guarantee that all regular singleton beans have been created * already. {@link ListableBeanFactory#getBeansOfType} calls within * this method won't trigger accidental side effects during bootstrap. * <p><b>NOTE:</b> This callback won't be triggered for singleton beans * lazily initialized on demand after {@link BeanFactory} bootstrap, * and not for any other bean scope either. Carefully use it for beans * with the intended bootstrap semantics only. */ void afterSingletonsInstantiated(); }
原理:
ioc容器創建並refresh()——》》finishBeanFactoryInitialization(beanFactory)——》》beanFactory.preInstantiateSingletons()
——》》smartSingleton.afterSingletonsInstantiated();
preInstantiateSingletons():
@Override public void preInstantiateSingletons() throws BeansException { if (this.logger.isDebugEnabled()) { this.logger.debug("Pre-instantiating singletons in " + this); } // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames); //創建並初始化所有的單實例bean // Trigger initialization of all non-lazy singleton beans... for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { @Override public Boolean run() { return ((SmartFactoryBean<?>) factory).isEagerInit(); } }, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } else { getBean(beanName); } } } // Trigger post-initialization callback for all applicable beans... for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName);
//判斷是否實現了該接口,是的話才回去調用這個方法 if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { smartSingleton.afterSingletonsInstantiated(); return null; } }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }
會調用EventListenerMethodProcessor的afterSingletonsInstantiated()
@Override public void afterSingletonsInstantiated() { List<EventListenerFactory> factories = getEventListenerFactories(); String[] beanNames = this.applicationContext.getBeanNamesForType(Object.class); for (String beanName : beanNames) { if (!ScopedProxyUtils.isScopedTarget(beanName)) { Class<?> type = null; try { type = AutoProxyUtils.determineTargetClass(this.applicationContext.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) { if (ScopedObject.class.isAssignableFrom(type)) { try { type = AutoProxyUtils.determineTargetClass(this.applicationContext.getBeanFactory(), ScopedProxyUtils.getTargetBeanName(beanName)); } 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); } } } } }
獲取所有的 BeanFactory,找到其中標注了 @EventListener 的方法,
利用反射和 DefaultEventListenerFactory 為其創建 ApplicationListener,並添加到事件派發器的緩存中。