SpringBoot-01 | SpringApplication.run
SpringBoot演进
SpringApplication:是Spring Boot引入的,于2014年发布。在Spring Boot 1.0 版本中首次出现,主要用于简化Spring应用程序的启动过程。它提供了自动配置、内嵌服务器等功能,使得开发者可以更方便地构建和运行Spring应用。
其他方式:
GenericApplicationContext:通用的ApplicationContext,可以通过编程方式加载和配置Bean,并启动Spring容器。
XmlBeanFactory:基于XML配置文件的Bean工厂,用于创建和管理Bean实例。
EmbeddedWebApplicationContext:嵌入式Web应用程序的ApplicationContext,用于在嵌入式服务器中启动Spring Web应用。
SpringBoot事件推送原型(观察者模式)
Initializers初始化
入口类:SampleWebUiApplication
入口直接点进去即可,先初始化,再调用run方法
public static void main(String[] args) {
SpringApplication.run(SampleWebUiApplication.class, args);
}
以下是初始化的代码逻辑
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 赋值主资源也是main方法的类。后面主要也是解析这个类,通过springboot注解可以了解到主类也是一个配置类。
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 将传入的primarySources设置到成员变量,一般设置为启用类
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 探测webApplicationType的类型。REACTIVE,NONE,SERVLET
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 加载初始化器,从META-INF/spring.factories中获取ApplicationContextInitializer配置(5个类)。SpringBoot自定义实现的一套功能
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 加载监听器,从META-INF/spring.factories中获取ApplicationListener配置(10个类)。SpringBoot自定义实现的一套功能
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 使用主动生成RuntimeException方式执行过程中获取包含main方法的类作为qi'dong'lei。
this.mainApplicationClass = deduceMainApplicationClass();
}
run启动
public ConfigurableApplicationContext run(String... args) {
// 创建 StopWatch 对象,并启动。StopWatch 主要用于简单统计 run 启动过程的时长。
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 准备空的ApplicationContext
ConfigurableApplicationContext context = null;
// 是否需要图形的配置headless属性:java.awt.headless,此属性是系统的一种配置模式,在系统允许缺少显示设备、键盘或鼠标这些外设的情况下工作,一般Linux服务器就在这种模式下工作
configureHeadlessProperty();
// 获取初始化时的14个监听器,详细见this.getSpringFactoriesInstances方法
SpringApplicationRunListeners listeners = getRunListeners(args);
// 批量启动监听器,for循环调用监听器starting方法,最终调用spring下每个listener.onApplicationEvent
// 调用监听器方法,用于手动触发已注册的监听器执行特定的业务逻辑,即:onApplicationEvent
listeners.starting();
try {
// 封装传入的参数,args是启动Spring应用的命令行参数,该参数可以在Spring应用中被访问。如:--server.port=9000
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 处理环境参数,创建并配置当前SpringBoot应用将要使用的Environment
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 设置参数spring.beaninfo.ignore,默认true
configureIgnoreBeanInfo(environment);
// 准备Banner打印器 - 就是启动Spring Boot的时候打印在console上的ASCII艺术字体
Banner printedBanner = printBanner(environment);
// 实例化对应的上下文类,比如web:"org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext",最终对spring的GenericWebApplicationContext上下文做了封装
// 这里重新实现了Spring的ServletWebServerApplicationContext类,
context = createApplicationContext();
// 这一步主要是在容器刷新之前的准备动作。包含一个非常关键的操作:将启动类注入容器,为后续开启自动化配置奠定基础。
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 调用 AbstractApplicationContext.refresh,启动spring容器, 进入spring的13个方法中。
refreshContext(context);
// 预留的扩展口子,如果有自定义需求,可以重写该方法。比如打印一些启动结束log,或者一些其它后置处理
afterRefresh(context, applicationArguments);
// 停止 StopWatch 统计时长
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 发布started事件,启动事件
// context.publishEvent,用于将自定义事件发布到应用程序上下文中,让相应的监听器自动接收并处理该事件,最终调用onApplicationEvent。
listeners.started(context);
// 调用 runner,实现了 ApplicationRunner或CommandLineRunner 的接口
// 用于调用项目中自定义的执行器XxxRunner类,使得在项目启动完成后立即执行一些特定程序
// Runner 运行器用于在服务启动时进行一些业务初始化操作,这些操作只在服务启动后执行一次。
// Spring Boot提供了ApplicationRunner和CommandLineRunner两种服务接口
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
// 发布running事件,应用上下文就绪事件
// 表示在前面一切初始化启动都没有问题的情况下,使用运行监听器SpringApplicationRunListener持续运行配置好的应用上下文ApplicationContext,
// 这样整个Spring Boot项目就正式启动完成了。
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}