spring boot实战(第三篇)事件监听源码分析
前言
解读源码,知其然知其所以然···
监听源码分析
首先来看下上一篇中执行的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);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
SpringApplication app = new SpringApplication(Application.class)
创建一个SpringApplication
实例;创建实例执行对象构造方法;其构造方法如下:
public SpringApplication(Object... sources) {
initialize(sources);
}
- 1
- 2
- 3
调用initialize()
,该方法执行若干初始化操作,在后续再继续深入该方法。
app.addListeners(new MyApplicationStartedEventListener());
调用SpringApplication
添加监听的方法执行操作:
public void addListeners(ApplicationListener<?>... listeners) {
this.listeners.addAll(Arrays.asList(listeners));
}
- 1
- 2
- 3
this.listeners
为List<ApplicationListener<?>>
类型,是SpringApplication
中所有监听器的持有容器(在initialize()
方法中也会往该监听集合中添加初始化的监听器)
执行完添加监听器方法后执行app.run(args)
方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
System.setProperty(
SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
Boolean.toString(this.headless)));
Collection<SpringApplicationRunListener> runListeners = getRunListeners(args);
for (SpringApplicationRunListener runListener : runListeners) {
runListener.started();
}
try {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, args);
for (SpringApplicationRunListener runListener : runListeners) {
runListener.environmentPrepared(environment);
}
if (this.showBanner) {
printBanner(environment);
}
// Create, load, refresh and run the ApplicationContext
context = createApplicationContext();
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
context.setEnvironment(environment);
postProcessApplicationContext(context);
applyInitializers(context);
for (SpringApplicationRunListener runListener : runListeners) {
runListener.contextPrepared(context);
}
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
}
// Load the sources
Set<Object> sources = getSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[sources.size()]));
for (SpringApplicationRunListener runListener : runListeners) {
runListener.contextLoaded(context);
}
// Refresh the context
refresh(context);
afterRefresh(context, args);
for (SpringApplicationRunListener runListener : runListeners) {
runListener.finished(context, null);
}
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(
getApplicationLog(), stopWatch);
}
return context;
}
catch (Throwable ex) {
try {
for (SpringApplicationRunListener runListener : runListeners) {
finishWithException(runListener, context, ex);
}
this.log.error("Application startup failed", ex);
}
finally {
if (context != null) {
context.close();
}
}
ReflectionUtils.rethrowRuntimeException(ex);
return context;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
在run()
方法中完成了spring boot的启动,方法代码比较长,本篇重点放在事件监听上;
Collection<SpringApplicationRunListener> runListeners = getRunListeners(args)
- 1
通过getRunListeners(args)
获取执行时监听的集合,其代码如下:
private Collection<SpringApplicationRunListener> getRunListeners(String[] args) {
List<SpringApplicationRunListener> listeners = new ArrayList<SpringApplicationRunListener>();
listeners.addAll(getSpringFactoriesInstances(SpringApplicationRunListener.class,
new Class<?>[] { SpringApplication.class, String[].class }, this, args));
return listeners;
}
- 1
- 2
- 3
- 4
- 5
- 6
重点关注
getSpringFactoriesInstances(SpringApplicationRunListener.class,
该方法获取执行类型子类实例集合
new Class<?>[] { SpringApplication.class, String[].class }, this, args)
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<String>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = new ArrayList<T>(names.size());
// Create instances from the names
for (String name : names) {
try {
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
Constructor<?> constructor = instanceClass.getConstructor(parameterTypes);
T instance = (T) constructor.newInstance(args);
instances.add(instance);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : "
+ name, ex);
}
}
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
看 SpringFactoriesLoader.loadFactoryNames(type, classLoader)
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
List<String> result = new ArrayList<String>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
String factoryClassNames = properties.getProperty(factoryClassName);
result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
}
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
其中
Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) ;
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
- 1
- 2
通过类加载器获取resources;FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
代码回去扫描项目工程中/META-INF下的spring.factories文件,获取org.springframework.boot.SpringApplicationRunListener
对应数据
在spring-boot-1.2.4.RELEASE
中可以找到如下信息
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
- 1
- 2
- 3
即通过Collection<SpringApplicationRunListener> runListeners = getRunListeners(args);
最终拿到的是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);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
将SpringApplication
中的监听器传递给SimpleApplicationEventMulticaster
实例multicaster
执行
for (SpringApplicationRunListener runListener : runListeners) { runListener.started(); }
- 1
- 2
- 3
调用EventPublishingRunListener
中的started()
方法
@Override
public void started() {
publishEvent(new ApplicationStartedEvent(this.application, this.args));
}
- 1
- 2
- 3
- 4
- 5
在该方法中首先创建一个ApplicationStartedEvent
事件,将this.application
传递过去,因此在执行ApplicationStartedEvent
监听时可以获取SpringApplication
实例。
执行publishEvent()
方法
private void publishEvent(SpringApplicationEvent event) {
this.multicaster.multicastEvent(event);
}
- 1
- 2
- 3
调用SimpleApplicationEventMulticaster#multicastEvent(event)
@Override
public void multicastEvent(final ApplicationEvent event) {
for (final ApplicationListener<?> listener : getApplicationListeners(event)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
在该代码中需要注意的是for循环中获取监听器集合方getApplicationListeners(event)
,由于传递的事件为ApplicationStartedEvent
,因此该方法需要获取到ApplicationStartedEvent
对应的监听器
protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event) {
Object source = event.getSource();
Class<?> sourceType = (source != null ? source.getClass() : null);
ListenerCacheKey cacheKey = new ListenerCacheKey(event.getClass(), 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(event, sourceType, retriever);
this.retrieverCache.put(cacheKey, retriever);
return listeners;
}
}
else {
// No ListenerRetriever caching -> no synchronization necessary
return retrieveApplicationListeners(event, sourceType, null);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
看retrieveApplicationListeners(event, sourceType, null)
方法;该方法代码比较长,截取一部分出来
private Collection<ApplicationListener<?>> retrieveApplicationListeners(
ApplicationEvent event, 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, event.getClass(), sourceType)) {
if (retriever != null) {
retriever.applicationListeners.add(listener);
}
allListeners.add(listener);
}
}
...
OrderComparator.sort(allListeners);
return allListeners;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
调用supportsEvent
方法判断对应的监听器是否支持指定的事件
protected boolean supportsEvent(ApplicationListener<?> listener,
Class<? extends ApplicationEvent> eventType, Class<?> sourceType) {
SmartApplicationListener smartListener = (listener instanceof SmartApplicationListener ?
(SmartApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
执行 GenericApplicationListenerAdapter#supportsEventType(eventType)
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) { Class<?> declaredEventType = resolveDeclaredEventType(this.delegate.getClass());
if (declaredEventType == null || declaredEventType.equals(ApplicationEvent.class)) {
Class<?> targetClass = AopUtils.getTargetClass(this.delegate); if (targetClass != this.delegate.getClass()) { declaredEventType = resolveDeclaredEventType(targetClass); } } return (declaredEventType == null || declaredEventType.isAssignableFrom(eventType)); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
调用resolveDeclaredEventType()
方法获取指定类继承的父类或实现接口时传递的泛型对应的类型,这句话有点绕口,可以自行看一下
static Class<?> resolveDeclaredEventType(Class<?> listenerType) { return GenericTypeResolver.resolveTypeArgument(listenerType, ApplicationListener.class); }
- 1
- 2
- 3
GenericTypeResolver
泛型解析工具类功能强大,我们在实际开发中同样可以利用。
至此getApplicationListeners(event)
调用完成,大体思路为:遍历所有的监听器,如果该监听器监听的事件为传递的事件或传递事件的父类则表示该监听器支持指定事件。
获取完指定事件对应监听器后,通过Executor
执行一个子线程去完成监听器listener.onApplicationEvent(event)
方法。
至此,事件监听源码解析结束,其他三个事件对应的源码和此类同。
本文转自http://blog.csdn.net/liaokailin/article/details/48194777