前面的文章详细讲解了spring boot框架中监听器的使用以及使用spring.factories文件中监听器的定义以及加载方式,Application Listeners,本章重点讲解这些定义的监听器是如何被spring boot调度触发的。
还是首先看一下上一篇中我们自己的main方法
入口
@RestController @SpringBootApplication() public class Application { @RequestMapping("/") String index() { return "shareniu"; } public static void main(String[] args) { SpringApplication springApplication = new SpringApplication(Application.class); springApplication.addListeners(new ShareniuApplicationStartedEventListener()); springApplication.run(args); } }
实例化SpringApplication类
实例化SpringApplication类的时候,会调用该类中的构造函数如下所示:
public SpringApplication(Object... sources) { initialize(sources); }
继续跟进initialize(sources);方法,本章我们将关注点放置到监听器的处理逻辑中,关于这一点一定要注意,看源码一定要有目的性的看。
private void initialize(Object[] sources) { if (sources != null && sources.length > 0) { this.sources.addAll(Arrays.asList(sources)); } this.webEnvironment = deduceWebEnvironment(); setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); }
上述代码,我们需要看2个方法
1.getSpringFactoriesInstances方法。
2.setListeners方法
getSpringFactoriesInstances方法
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
看到getSpringFactoriesInstances方法,就非常的熟悉,可以参考spring boot读取properties文件spring.factories。
该方法执行完毕之后可以获取到的监听器如下:
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.cloudfoundry.VcapApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,\
org.springframework.boot.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.logging.LoggingApplicationListener
setListeners方法
public void setListeners(Collection<? extends ApplicationListener<?>> listeners) { this.listeners = new ArrayList<ApplicationListener<?>>(); this.listeners.addAll(listeners); }
首先实例化listeners集合,然后将所有的监听器添加进去。明白了这个问题就简单多了。接下来继续看我们自己代码中的addListeners方法。
SpringApplication类中的addListeners方法
private List<ApplicationListener<?>> listeners; public void addListeners(ApplicationListener<?>... listeners) { this.listeners.addAll(Arrays.asList(listeners)); }
这个方法比较简单,直接将添加的监听器放到SpringApplication类中的listeners集合中。换言之,所有的监听器最终均存储在SpringApplication类中的listeners集合中。
接下来看一下springApplication.run(args)方法。
springApplication.run(args)
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.started(); try { context = doRun(listeners, args); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted( getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { try { listeners.finished(context, ex); this.log.error("Application startup failed", ex); } finally { if (context != null) { context.close(); } } ReflectionUtils.rethrowRuntimeException(ex); return context; } }
我们将关注点放到如下两行代码中:
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.started();
getRunListeners(args)
getRunListeners(args)方法如下:
private final Log log = LogFactory.getLog(getClass()); private SpringApplicationRunListeners getRunListeners(String[] args) { Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class }; return new SpringApplicationRunListeners(this.log, getSpringFactoriesInstances( SpringApplicationRunListener.class, types, this, args)); }
上述方法中,首先我们看一下getSpringFactoriesInstances方法,这个比较简单了,还是参考spring boot读取properties文件spring.factories。在这里注意一点:
SpringApplicationRunListener对应的配置内容如下:
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
换言之,SpringApplicationRunListener接口的默认实现类为EventPublishingRunListener。
EventPublishingRunListener类
在实例化EventPublishingRunListener类的时候,会调用该类的无参构造函数,如下所示:
public EventPublishingRunListener(SpringApplication application, String[] args) { this.application = application; this.args = args; this.multicaster = new SimpleApplicationEventMulticaster(); for (ApplicationListener<?> listener : application.getListeners()) { this.multicaster.addApplicationListener(listener); } }
最核心的地方在于:通过SpringApplication实例对象获取到所有的监听器集合,并将其添加到multicaster类中,也就是SimpleApplicationEventMulticaster类实例对象。
listeners.started方法
上面的代码明白之后,接下来我们就开始看一下listeners.started()方法,该方法的定义如下:
SpringApplicationRunListeners类:
public void started() { for (SpringApplicationRunListener listener : this.listeners) { listener.started(); } }
循环遍历所有的listeners,并依此调用SpringApplicationRunListener中的started方法。
最终调用EventPublishingRunListener类中的started方法:
public void started() { publishEvent(new ApplicationStartedEvent(this.application, this.args)); }
该方法直接实例化ApplicationStartedEvent事件类,并为其设置application对象。然后调用publishEvent方法:
private void publishEvent(SpringApplicationEvent event) { this.multicaster.multicastEvent(event); }
最终调用SimpleApplicationEventMulticaster类中的multicastEvent方法如下所示:
public void multicastEvent(ApplicationEvent event) { multicastEvent(event, resolveDefaultEventType(event)); }
最终调用如下代码:
@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); } } }
上述代码中,首先循环遍历getApplicationListeners(event, type),然后调用getTaskExecutor()方法获取executor ,如果executor 不为空则调用,否则直接调用invokeListener(listener, event)方法。
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(); } 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); } }
其中retrieveApplicationListeners(eventType, sourceType, null)核心代码如下:
private Collection<ApplicationListener<?>> retrieveApplicationListeners( ResolvableType eventType, Class<?> sourceType, ListenerRetriever retriever) { LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>(); Set<ApplicationListener<?>> listeners; Set<String> listenerBeans; synchronized (this.retrievalMutex) { listeners = 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)) { 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); return allListeners; }
上述代码重点在supportsEvent(listener, eventType, sourceType)方法,其实现如下:
protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, Class<?> sourceType) { GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ? (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener)); return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType)); }
GenericApplicationListenerAdapter构造函数
public GenericApplicationListenerAdapter(ApplicationListener<?> delegate) { Assert.notNull(delegate, "Delegate listener must not be null"); this.delegate = (ApplicationListener<ApplicationEvent>) delegate; this.declaredEventType = resolveDeclaredEventType(this.delegate); } private static ResolvableType resolveDeclaredEventType(ApplicationListener<ApplicationEvent> listener) { ResolvableType declaredEventType = resolveDeclaredEventType(listener.getClass()); if (declaredEventType == null || declaredEventType.isAssignableFrom( ResolvableType.forClass(ApplicationEvent.class))) { Class<?> targetClass = AopUtils.getTargetClass(listener); if (targetClass != listener.getClass()) { declaredEventType = resolveDeclaredEventType(targetClass); } } return declaredEventType; }
其中resolveDeclaredEventType方法如下:
static ResolvableType resolveDeclaredEventType(Class<?> listenerType) { ResolvableType resolvableType = ResolvableType.forClass(listenerType).as(ApplicationListener.class); if (resolvableType == null || !resolvableType.hasGenerics()) { return null; } return resolvableType.getGeneric(); }
执行GenericApplicationListenerAdapter类中的supportsEventType方法:
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) { Class<?> typeArg = GenericTypeResolver.resolveTypeArgument(this.delegate.getClass(), ApplicationListener.class); if (typeArg == null || typeArg.equals(ApplicationEvent.class)) { Class<?> targetClass = AopUtils.getTargetClass(this.delegate); if (targetClass != this.delegate.getClass()) { typeArg = GenericTypeResolver.resolveTypeArgument(targetClass, ApplicationListener.class); } } return (typeArg == null || typeArg.isAssignableFrom(eventType)); }
总结
再次总结一下监听器的逻辑
遍历所有的监听器以及初始化内置监听器,如果监听器的事件为传递的或者传递事件的父类则表示监听器支持指定的事件。
通过getTaskExecutor获取Executor来开启一个线程执行监听器。
触发监听器。
欢迎关注微信公众号,您的肯定是对我最大的支持
转载请注明:分享牛 » spring boot监听器源码分析