说明:本系列的spring boot版本为2.1.1.RELEASE。
启动
引入和启动一个SpringBoot的项目非常简单,maven导入jar包后,一个最简单的SpringBoot项目只需一个注解和一行代码。
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(DemoApplication.class);
springApplication.run(args);
}
}
SpringApplication有很多属性,我们可以在run之前用set方法赋予成员变量的属性,也可以用构建者模式赋予变量属性,这两种方式本质上没有区别。
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(DemoApplication.class)
.build()
.run(args);
}
}
实例化
SpringApplication->SpringApplication():
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 设置servlet环境
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 成员变量initializers设置ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
// 成员变量listeners添加监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 将main方法所在类设置为主应用类
this.mainApplicationClass = deduceMainApplicationClass();
getSpringFactoriesInstances()方法,根据传过来的Class调用SpringFactoriesLoader.loadFactoryNames()得到配置文件spring.factories中的全限定名,然后利用反射实例化,最终返回一个List集合。
监听器与Tomcat中的监听器作用如出一辙,当生命周期变化时,监听器将会处理对应的事件。
前言:
运行监听器类SpringApplicationRunListeners
实例化完成后,调用run()方法
SpringApplication->run():
// getRunListeners(args)得到配置文件中指定
// org.springframework.boot.SpringApplicationRunListener的属性
SpringApplicationRunListeners listeners = getRunListeners(args);
// 注意run方法下所有的listeners都是运行监听器
listeners.starting();
getRunListeners(args)从spring.factories中得到运行监听器,在SpringBoot中只有EventPublishingRunListener,顾名思义与事件的发布有关,最后封装成SpringApplicationRunListeners类返回。
SpringApplicationRunListeners->starting():
for (SpringApplicationRunListener listener : this.listeners) {
listener.starting();
}
EventPublishingRunListener->starting():
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
SimpleApplicationEventMulticaster->multicastEvent():
multicastEvent(event, resolveDefaultEventType(event));
注意到这里的事件类型为应用启动事件ApplicationStartingEvent,它是抽象类SpringApplicationEvent的子类,实际上SpringBoot的所有事件类都是SpringApplicationEvent的子类。
SimpleApplicationEventMulticaster->multicastEvent():
// 先遍历所有监听器,得到支持ApplicationStartingEvent事件类型及SpringApplication类的监听器
// 再遍历监听器,处理对应的事件
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
invokeListener(listener, event);
}
SimpleApplicationEventMulticaster->invokeListener():
doInvokeListener(listener, event);
SimpleApplicationEventMulticaster->doInvokeListener():
listener.onApplicationEvent(event);
本例中SpringBoot的监听器如下图所示
监听器是否支持事件类型最终由supportsEvent()决定,最终决策如下流程图
监听器类都需要实现ApplicationListener接口,它的泛型是ApplicationEvent或其子类,图中的泛型类即为此。
自定义监听器类
附录:banner
启动方法中注意到有这样的一行代码Banner printedBanner = printBanner(environment);(前面的过程暂且先不管)。
SpringApplication->printBanner():
// 默认在控制台打印
return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
SpringApplicationBannerPrinter->print():
Banner banner = getBanner(environment);
banner.printBanner(environment, sourceClass, out);
SpringApplicationBannerPrinter->getBanner():
banners.addIfNotNull(getImageBanner(environment));
banners.addIfNotNull(getTextBanner(environment));
getImageBanner()获取配置文件中spring.banner.image.location设置的路径,如果没有的话,尝试依次读取resources目录下的bannner.gif, bannner.jpg, bannner.png,设置了任意一文件就返回;getTextBanner()获取配置文件中spring.banner.location设置的路径,如果没有的话,尝试读取resources目录下的bannner.txt。这两个方法哪个有就打印哪个,都没有的话打印默认banner(SpringBoot的logo)。
还可以给bannner设置字体,颜色,版本号等属性,具体可以研究源代码(位于ResourceBanner->printBanner()),下图是设置为佛祖保佑打印出来的效果。