(转)spring boot实战(第三篇)事件监听源码分析
2017-04-14 17:22
876 查看
原文:http://blog.csdn.net/liaokailin/article/details/48194777
调用
执行完添加监听器方法后执行
在
通过
重点关注
看
其中
通过类加载器获取resources;
在
即通过SpringApplicationRunListeners listeners = this.getRunListeners(args);最终拿到的是
(这里还要做一个详细的回顾)
在获取
将
执行
调用
在该方法中首先创建一个
执行
(这里还要分析一下multicaster接口的初始化)
调用
在该代码中需要注意的是for循环中获取监听器集合方
看
调用
执行
至此
获取完指定事件对应监听器后,通过
监听源码分析
首先是我们自定义的main方法:package com.lkl.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import com.lkl.springboot.listener.MyApplicationStartedEventListener; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication app = new SpringApplication(Application.class); //app.setAdditionalProfiles("dev"); app.addListeners(new MyApplicationStartedEventListener()); app.run(args); } }
SpringApplication app = new SpringApplication(Application.class)创建一个
SpringApplication实例;创建实例执行对象构造方法;其构造方法如下:
public SpringApplication(Object... sources) { this.bannerMode = Mode.CONSOLE; this.logStartupInfo = true; this.addCommandLineProperties = true; this.headless = true; this.registerShutdownHook = true; this.additionalProfiles = new HashSet(); this.initialize(sources); }
调用
initialize(),该方法执行若干初始化操作,在后续再继续深入该方法。
app.addListeners(new MyApplicationStartedEventListener());调用
SpringApplication添加监听的方法执行操作:
public void addListeners(ApplicationListener... listeners) { this.listeners.addAll(Arrays.asList(listeners)); }
this.listeners为
List<ApplicationListener<?>>类型,是
SpringApplication中所有监听器的持有容器(在
initialize()方法中也会往该监听集合中添加初始化的监听器)
执行完添加监听器方法后执行
app.run(args)方法
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; this.configureHeadlessProperty(); SpringApplicationRunListeners listeners = this.getRunListeners(args); listeners.started(); try { DefaultApplicationArguments ex = new DefaultApplicationArguments(args); context = this.createAndRefreshContext(listeners, ex); this.afterRefresh(context, (ApplicationArguments)ex); listeners.finished(context, (Throwable)null); stopWatch.stop(); if(this.logStartupInfo) { (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); } return context; } catch (Throwable var6) { this.handleRunFailure(context, listeners, var6); throw new IllegalStateException(var6); } }
在
run()方法中完成了spring boot的启动,方法代码比较长,本篇重点放在事件监听上;
SpringApplicationRunListeners listeners = this.getRunListeners(args);
通过
getRunListeners(args)获取执行时监听的集合,其代码如下:
private SpringApplicationRunListeners getRunListeners(String[] args) { Class[] types = new Class[]{SpringApplication.class, String[].class}; return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, new Object[]{this, args})); }
重点关注
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args)
这个方法返回
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); LinkedHashSet names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
看
SpringFactoriesLoader.loadFactoryNames(type, classLoader)
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); try { Enumeration ex = classLoader != null?classLoader.getResources("META-INF/spring.factories"):ClassLoader.getSystemResources("META-INF/spring.factories"); ArrayList result = new ArrayList(); while(ex.hasMoreElements()) { URL url = (URL)ex.nextElement(); Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); String factoryClassNames = properties.getProperty(factoryClassName); result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); } return result; } catch (IOException var8) { throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8); } }
其中
Enumeration ex = classLoader != null?classLoader.getResources("META-INF/spring.factories"):ClassLoader.getSystemResources("META-INF/spring.factories");
通过类加载器获取resources;
"META-INF/spring.factories";代码会去扫描项目工程中/META-INF下的spring.factories文件,获取
org.springframework.boot.SpringApplicationRunListener对应数据
在
spring-boot-1.3.6.RELEASE中可以找到如下信息
# Run Listeners org.springframework.boot.SpringApplicationRunListener=\ org.springframework.boot.context.event.EventPublishingRunListener
即通过SpringApplicationRunListeners listeners = this.getRunListeners(args);最终拿到的是
EventPublishingRunListener。
(这里还要做一个详细的回顾)
在获取
EventPublishingRunListener实例时,执行对应构造方法
public EventPublishingRunListener(SpringApplication application, String[] args) { this.application = application; this.args = args; this.multicaster = new SimpleApplicationEventMulticaster(); Iterator var3 = application.getListeners().iterator(); while(var3.hasNext()) { ApplicationListener listener = (ApplicationListener)var3.next(); this.multicaster.addApplicationListener(listener); } }
将
SpringApplication中的监听器传递给
SimpleApplicationEventMulticaster实例
multicaster
执行
SpringApplicationRunListeners listeners = this.getRunListeners(args); listeners.started();
public void started() { Iterator var1 = this.listeners.iterator(); while(var1.hasNext()) { SpringApplicationRunListener listener = (SpringApplicationRunListener)var1.next(); listener.started(); } }
调用
EventPublishingRunListener中的
started()方法
public void started() { this.publishEvent(new ApplicationStartedEvent(this.application, this.args)); }
在该方法中首先创建一个
ApplicationStartedEvent事件,将
this.application传递过去,因此在执行
ApplicationStartedEvent监听时可以获取
SpringApplication实例。
执行
publishEvent()方法(这里就开始执行监听事件后调用的方法了)
private void publishEvent(SpringApplicationEvent event) { this.multicaster.multicastEvent(event); }
(这里还要分析一下multicaster接口的初始化)
调用
SimpleApplicationEventMulticaster#multicastEvent(event)
public void multicastEvent(ApplicationEvent event) { this.multicastEvent(event, this.resolveDefaultEventType(event)); } public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) { ResolvableType type = eventType != null?eventType:this.resolveDefaultEventType(event); Iterator var4 = this.getApplicationListeners(event, type).iterator(); while(var4.hasNext()) { final ApplicationListener listener = (ApplicationListener)var4.next(); Executor executor = this.getTaskExecutor(); if(executor != null) { executor.execute(new Runnable() { public void run() { SimpleApplicationEventMulticaster.this.invokeListener(listener, event); } }); } else { this.invokeListener(listener, event); } } }
在该代码中需要注意的是for循环中获取监听器集合方
getApplicationListeners(event),由于传递的事件为
ApplicationStartedEvent,因此该方法需要获取到
ApplicationStartedEvent对应的监听器
protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) { Object source = event.getSource(); Class sourceType = source != null?source.getClass():null; AbstractApplicationEventMulticaster.ListenerCacheKey cacheKey = new AbstractApplicationEventMulticaster.ListenerCacheKey(eventType, sourceType); AbstractApplicationEventMulticaster.ListenerRetriever retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey); if(retriever != null) { return retriever.getApplicationListeners(); } else if(this.beanClassLoader == null || ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader))) { Object var7 = this.retrievalMutex; synchronized(this.retrievalMutex) { retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey); if(retriever != null) { return retriever.getApplicationListeners(); } else { retriever = new AbstractApplicationEventMulticaster.ListenerRetriever(true); Collection listeners = this.retrieveApplicationListeners(eventType, sourceType, retriever); this.retrieverCache.put(cacheKey, retriever); return listeners; } } } else { return this.retrieveApplicationListeners(eventType, sourceType, (AbstractApplicationEventMulticaster.ListenerRetriever)null); } }
看
retrieveApplicationListeners(event, sourceType, null)方法;
private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, Class<?> sourceType, AbstractApplicationEventMulticaster.ListenerRetriever retriever) { LinkedList allListeners = new LinkedList(); Object beanFactory = this.retrievalMutex; LinkedHashSet listeners; LinkedHashSet listenerBeans; synchronized(this.retrievalMutex) { listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners); listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans); } Iterator beanFactory1 = listeners.iterator(); while(beanFactory1.hasNext()) { ApplicationListener listener = (ApplicationListener)beanFactory1.next(); if(this.supportsEvent(listener, eventType, sourceType)) { if(retriever != null) { retriever.applicationListeners.add(listener); } allListeners.add(listener); } } if(!listenerBeans.isEmpty()) { BeanFactory beanFactory2 = this.getBeanFactory(); Iterator listener2 = listenerBeans.iterator(); while(listener2.hasNext()) { String listenerBeanName = (String)listener2.next(); try { Class listenerType = beanFactory2.getType(listenerBeanName); if(listenerType == null || this.supportsEvent(listenerType, eventType)) { ApplicationListener listener1 = (ApplicationListener)beanFactory2.getBean(listenerBeanName, ApplicationListener.class); if(!allListeners.contains(listener1) && this.supportsEvent(listener1, eventType, sourceType)) { if(retriever != null) { retriever.applicationListenerBeans.add(listenerBeanName); } allListeners.add(listener1); } } } catch (NoSuchBeanDefinitionException var13) { ; } } } AnnotationAwareOrderComparator.sort(allListeners); return allListeners; }
调用
supportsEvent方法判断对应的监听器是否支持指定的事件
protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, Class<?> sourceType) { Object smartListener = listener instanceof GenericApplicationListener?(GenericApplicationListener)listener:new GenericApplicationListenerAdapter(listener); return ((GenericApplicationListener)smartListener).supportsEventType(eventType) && ((GenericApplicationListener)smartListener).supportsSourceType(sourceType); }
执行
GenericApplicationListenerAdapter#supportsEventType(eventType)
public boolean supportsEventType(ResolvableType eventType) { if(this.delegate instanceof SmartApplicationListener) { Class eventClass = eventType.getRawClass(); return ((SmartApplicationListener)this.delegate).supportsEventType(eventClass); } else { return this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType); } }
GenericTypeResolver泛型解析工具类功能强大,我们在实际开发中同样可以利用。
至此
getApplicationListeners(event)调用完成,大体思路为:遍历所有的监听器,如果该监听器监听的事件为传递的事件或传递事件的父类则表示该监听器支持指定事件。
获取完指定事件对应监听器后,通过
Executor执行一个子线程去完成监听器
listener.onApplicationEvent(event)方法。
相关文章推荐
- spring boot实战(第三篇)事件监听源码分析
- spring boot实战(第三篇)事件监听源码分析
- spring boot实战(第三篇)事件监听源码分析
- spring boot实战(第十篇)Spring boot Bean加载源码分析
- spring boot实战(第十四篇)整合RabbitMQ源码分析前言
- spring boot实战(第二篇)事件监听
- spring boot实战(第十篇)Spring boot Bean加载源码分析
- Spring Boot - security 实战与源码分析
- spring boot实战(第十四篇)整合RabbitMQ源码分析前言
- Spring Boot 揭秘与实战 源码分析 - 工作原理剖析
- Spring Boot启动过程源码分析(二)事件监听器
- springboot源码分析14-事件发布机制以及应用监听器
- spring boot实战(第二篇)事件监听
- spring boot实战(第六篇)加载application资源文件源码分析
- spring boot实战(第十篇)Spring boot Bean加载源码分析
- springboot源码分析14-事件发布机制以及应用监听器
- spring boot实战(第九篇)Application创建源码分析
- Spring boot实战中Application创建源码分析
- spring boot实战(第六篇)加载application资源文件源码分析
- spring boot实战(第十篇)Spring boot Bean加载源码分析