您的位置:首页 > 编程语言 > Java开发

(转)spring boot实战(第三篇)事件监听源码分析

2017-04-14 17:22 876 查看
原文:http://blog.csdn.net/liaokailin/article/details/48194777

监听源码分析

首先是我们自定义的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)
方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: