今天开始调试SpringBoot2.1.0框架,先从最基本的没有任何组件的SpringBoot开始调试,调试的入口是@SpringBootApplication注解定义的主程序入口类的main方法:
main方法内只调用了一个方法——SpringApplication的run方法,传入的参数是主程序入口类DemoApplication的类类型和命令行参数。先看SpringApplication的doc介绍:
用来从Java main方法启动(bootstrap)和登陆( launch)Spring应用的类,默认会执行以下步骤来启动应用:
- 创建合适的ApplicationContext实例(依赖于定义的classpath)。
- 注册CommandLinePropertySource获取命令行参数作为Spring的属性。
- 更新应用上下文,加载所有的单例beans。
- 触发所有CommandLineRunner beans。
大部分情况下,可以用java main方法里直接调用静态run方法的方法启动你的应用程序,即如上图显示的方式。更高级配置可以通过在调用run方法之前新建SpringApplication并订制其属性来完成。
SpringApplication可以从不同的源读取beans,推荐方式是利用单个配置类Configuration来启动应用程序,当然也可以设置getSources()从以下地方读取源:
- 被AnnotatedBeanDefinitionReader加载的完全限定类名。
- 被XmlBeanDefinitionReader加载的XMl资源文件地址或者被GroovyBeanDefinitionReader加载的groovy脚本地址。
- 被ClassPathBeanDefinitionScanner扫描的包名。
Configuration属性也会绑定到SpringApplication,这样可以动态地设置SpringApplication属性。
再来看run方法的doc介绍:
可以从指定的源使用默认的设置来运行SpringApplication的静态helper。
run方法内部细节:
返回另一个run方法的调用,传入参数是包装了DemoApplication的数组,和命令行参数,这意味着run方法可以同时启动多个应用程序。再看另一run方法的内部细节:
此处用传入的包装了DemoApplication的数组新建了一个SpringApplication实例,并返回run方法调用,进入SpringApplication的构造过程看看:
此构造器的doc介绍是:
创建SpringApplication实例,应用上下文会加载beans从指定的primarySources。
此处调用了另一个构造器:
这里给SpringApplication实例初始化了六个私有属性:
- ResourceLoader:加载资源的接口 。
- primarySources:包装成LinkedHashSet的主程序入口类,用于加载beans。
- WebApplicationType:web应用类型,三种取值(null不开启内嵌web server, sevlet基于servlet的内嵌web server开启, reactive开启基于reactive的内嵌web server)。
- ApplicationContextInitializer:包装在List中,用于初始化ConfigurableApplicationContext的回调接口。
- ApplicationListener:包装在List中,应用程序事件监听器。
- mainApplicationClass:主程序类,定义了main方法的应用程序入口类。
初始化完毕后,调用真正的SpringApplication实例的run方法:
今天先到这,明天继续。