点击上方蓝色字体,选择“标星公众号”
优质文章,第一时间送达
作者 | yangxiaohui227
来源 | urlify.cn/6jeaiu
66套java从入门到精通实战课程分享
测试项目,随便一个简单的springboot项目即可:
直接debug调试:
可见,分2步,第一步是创建SpringApplication对象,第二步是调用run方法:
1.SpringApplication对象的创建过程:
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) { //resourceLoader为null,因为我们没有传入,primarySources这里包含主启动类的ThymeleafApplication.class
this.resourceLoader = resourceLoader; //资源加载器,这里是null
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); //将主启动类字节码存起来
this.webApplicationType = WebApplicationType.deduceFromClasspath(); //检测当前的项目web类型,后续会分析
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));//这里涉及springboot的一个重要知识点,后续分析
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));//这里涉及springboot的一个重要知识点,后续分析
this.mainApplicationClass = deduceMainApplicationClass();//这里检测main方法所在的类
}
通过SpringApplication的创建过程,我们分析下,它的主要几个方法:
this.webApplicationType = WebApplicationType.deduceFromClasspath();
因为我引入的是springboot-web相关依赖,所以,在本次测试项目中,webApplication的类型是AnnotationConfigServletWebServerApplicationContext
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class))和setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)):
后续很多地方也会用到这个功能,在此解析下:所以上面2个方法分别是从spring.factories文件中,找到key为org.springframework.context.ApplicationContextInitializer 的所有值,然后创建对应的实例,另一个ApplicationListener同理
接下来我们分析下:this.mainApplicationClass = deduceMainApplicationClass();
检测main方法所在的类,我们自己写的代码,自己肯定很容易知道是哪个类,但springboot框架不知道,那怎么检测呢,我们先看一个异常栈信息:
如上图所示,我们只要从一个异常的堆栈中就可以获取到main方法了,所以源码检测main方法也是一样的:
至此SpringApplication对象创建完毕,后续我们分析下它的run方法都做了些啥:
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch(); //一个计时器,用于计算启动的时间
stopWatch.start();//计时开始
ConfigurableApplicationContext context = null;
Collection exceptionReporters = new ArrayList<>();//异常报告器列表
configureHeadlessProperty();//这个是给System对象设置一个属性:java.awt.headless=true
SpringApplicationRunListeners listeners = getRunListeners(args); //从spring.factories文件中读取SpringApplicationRunListener的实现类,并创建对应的实例,这个类后续分析
listeners.starting();//调用监听器的starting方法
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); //这里仅仅是对请求参数进行封装成一个对象
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);//创建并配置环境的一些属性,然后调用监听器的相应方法,后续会分析
configureIgnoreBeanInfo(environment);//往System对象中设置属性spr