1.Run方法代码如下
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//创建DefualtBootstrapContext对象
DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
ConfigurableApplicationContext context = null;
this.configureHeadlessProperty();
//从这里开始,构建监听事件,并启动监听事件
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
2.查看this.getRunListeners(args)代码
private SpringApplicationRunListeners getRunListeners(String[] args) {
//这里再次出现getSpringFactoriesInstances方法,直接去缓存中拿到spring.factories中的配置类,并进行初始化
Class<?>[] types = new Class[]{SpringApplication.class, String[].class};
return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args), this.applicationStartup);
}
3.查看getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args)的方法具体做了哪些事
可以看见,从spring.factories中,找个了一个对应的事件,org.springframework.boot.context.event.EventPublishingRunListener,然后方法向下走的时候,通过反射创建此事件对象的创建,代码如下
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList(names.size());
Iterator var7 = names.iterator();
while(var7.hasNext()) {
String name = (String)var7.next();
try {
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
//这里开始进行对象的创建
T instance = BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
} catch (Throwable var12) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, var12);
}
}
return instances;
}
4.查看EventPublishingRunListener的构造方法
public EventPublishingRunListener(SpringApplication application, String[] args) {
//这里将SpringApplication对象赋值到application属性,并获取SpringApplication对象中的listener
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
//application中的listener对象进行迭代,并加入到EventPublishingRunListener类的广播属性中
Iterator var3 = application.getListeners().iterator();
while(var3.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var3.next();
this.initialMulticaster.addApplicationListener(listener);
}
}
上一章SpringApplication对象构建中,已经提到了listener属性有哪些值,这里就不再阐述,直接贴图
可以看到这里有9个Listener,我们看下this.initialMulticaster.addApplicationListener(listener);这一行代码做了哪些事
public void addApplicationListener(ApplicationListener<?> listener) {
AbstractApplicationEventMulticaster.DefaultListenerRetriever var2 = this.defaultRetriever;
synchronized(this.defaultRetriever) {
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
//将这9个Listener添加到defaultRetriever对象的applicationListeners属性中,
这个属性是一个LinkedHashSet
this.defaultRetriever.applicationListeners.add(listener);
this.retrieverCache.clear();
}
}
到这里this.getSpringFactoriesInstances方法基本执行结束,之后再创建SpringApplicationRunListeners对象,看一下SpringApplicationRunListener对象到构造方法
SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners, ApplicationStartup applicationStartup) {
this.log = log;
//这里到listeners就是封装好的EventPublishingRunListener对象
this.listeners = new ArrayList(listeners);
this.applicationStartup = applicationStartup;
}
这里我们可以看到SpringApplicationRunListeners的listener属性已经赋值了构建好的EventPublishingRunListener,下一步我们SpringApplicationRunListeners的starting方法
5.查看SpringApplicationRunListeners的starting方法代码
void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
//这里使用了Java8的Consumer接口,函数式编程
this.doWithListeners("spring.boot.application.starting", (listener) -> {
listener.starting(bootstrapContext);
}, (step) -> {
if (mainApplicationClass != null) {
step.tag("mainApplicationClass", mainApplicationClass.getName());
}
});
}
//我们看一下这个doWithListeners方法
/*
第一个参数式一个stepName,传入的字符串spring.boot.application.starting
第二个参数是Consumer<SpringApplicationRunListener> listenerAction
(listener) -> {
listener.starting(bootstrapContext);
}
方法里面this.listeners.forEach(listenerAction);就是将SpringApplicationRunListener中的listener循环的调用starting方法,这里的listener就只有一个对象EventPublishingRunListener,所以就会调用该对象的starting方法
*/
private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction, Consumer<StartupStep> stepAction) {
StartupStep step = this.applicationStartup.start(stepName);
this.listeners.forEach(listenerAction);
if (stepAction != null) {
stepAction.accept(step);
}
step.end();
}
6.我们看一下EventPublishingRunListener的starting方法
//这里,创建了一个ApplicationStartingEvent事件对象,事件对象的构建方法中,将SpringApplication设置为source属性,可见下图
public void starting(ConfigurableBootstrapContext bootstrapContext) {
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
}
我们看一下multicastEvent方法
public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
//这里获取Executor接口实现,默认为null,可以给这个taskExecutor设置自定义的Executor实现多线 程处理
Executor executor = this.getTaskExecutor();
//这里返回的迭代器是listener迭代
Iterator var5 = this.getApplicationListeners(event, type).iterator();
while(var5.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var5.next();
if (executor != null) {
executor.execute(() -> {
this.invokeListener(listener, event);
});
} else {
//这里调用SpringApplication中的listener
this.invokeListener(listener, event);
}
}
}
//代码debug到this.invokeListener(listener,event)
```java
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
//可以看到这里调用了每一个listener自己的onApplicationEvent方法,启动事件监听
listener.onApplicationEvent(event);
} catch (ClassCastException var6) {
String msg = var6.getMessage();
if (msg != null && !this.matchesClassCastMessage(msg, event.getClass()) && (!(event instanceof PayloadApplicationEvent) || !this.matchesClassCastMessage(msg, ((PayloadApplicationEvent)event).getPayload().getClass()))) {
throw var6;
}
Log loggerToUse = this.lazyLogger;
if (loggerToUse == null) {
loggerToUse = LogFactory.getLog(this.getClass());
this.lazyLogger = loggerToUse;
}
if (loggerToUse.isTraceEnabled()) {
loggerToUse.trace("Non-matching event type for listener: " + listener, var6);
}
}
}
到此,Springboot启动流程中,事件监听就结束了!!!