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,并添加到事件派发器的缓存中。