小言_互联网的博客

【SpringBoot3.0源码】启动流程源码解析 • 上

505人阅读  评论(0)

文章目录

SpringBoot启动类:

@SpringBootApplication
public class AppRun {
   
    public static void main(String[] args) {
   
        SpringApplication.run(AppRun.class, args);
    }
}

步入SpringApplication.run(AppRun.class, args)方法:
这里分为两步:

  1. 创建一个SpringApplication实例:初始化一些配置(包括初始化对象和监听器以及一些配置文件)
  2. 调用run方法。
new SpringApplication(primarySources).run(args)

初始化

步入SpringApplication的构造方法中:

首先获取资源加载器、保存primarySources属性、web类型,设置初始化器和监听器,获取main方法所在的类

重点看一下获取初始化器和监听器这部分。


在此之前,看一下271行的代码:
在SpringBoot的老版本中,是没有这快代码的,这里主要是提前加载一些初始化器、监听器和其他配置放入缓存中,以便后续获取。

this.bootstrapRegistryInitializers = new ArrayList<>(
				getSpringFactoriesInstances(BootstrapRegistryInitializer.class));

步入getSpringFactoriesInstances方法中:

最终来到这里:这里首先构造一个加载器,再去调用load方法。


步入forDefaultResourceLocation方法:
最终来到这里:

注意332行代码:如果loaders这个map中有resourceLacation,则返回该key值对应的value。

当然,这里显然是没有的。所以会加载后面的函数,存入loaders中,并返回该值。

先看看loadFactoriesResource方法做了什么:

首先将项目中含有META-INFO/spring.factories的文件路径加载出来,这里有2个url,一个是autoconfigrition下的,一个是aop下的。

处理完之后去重。

最后收集到18个,包括初始化器和监听器等。

紧接着调用Collections.unmodifiableMap(result)方法。

看看Collections.unmodifiableMap(result)这个方法:

最后将map存入m这个属性中。


分析完SpringFactoriesLoader的参数了,来看看它的构造方法吧:

这样,factories就存入了我们加载出来的类。

构建完加载器,回去调用这个load方法:

步入loadFactoryNames方法:

最后会在m这个缓存中取值。

当然这里什么都没有,最后返回null。

回到最初这里:


后面两行代码,应该就很清晰了,因为调用的都是同一个getSpringFactoriesInstances方法,因为前者已经加载完配置文件,所以后面这里设置初始化器和监听器会从我们设置好的那个m缓存中获取。

setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

值得注意的是,再次从m这个缓存中获取的时候,我们会取到值,那么这个for循环就会执行:

这里首先会通过反射创建该对象的实例,再add到result的List集合中。


转载:https://blog.csdn.net/CSDN_SAVIOR/article/details/129007828
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场