Springboot源码解析之启动流程-01

highlight: a11y-dark不管是工作还是面试 深入了解SpringBoot源码 都将给你带来非常实实在在的收获so 今天我们来揭开SpringBoot的第一个面纱(run方法)。1.初始化.搭建阅读环境 springboot版本为 2.1.x github fork或者下载: https://github.com/spring-projects/spring-...
摘要由CSDN通过智能技术生成

highlight: a11y-dark

不管是工作还是面试 深入了解SpringBoot源码 都将给你带来非常实实在在的收获 so 今天我们来揭开SpringBoot的第一个面纱(run方法)。

1.初始化.搭建阅读环境 springboot版本为 2.1.x

github fork或者下载: https://github.com/spring-projects/spring-boot/tree/v2.1.0.RELEASE

#### 下载后 idea打开 由于springboo默认没将其写到父pom的modles中 所以我们将spring-boot-samples导入,执行 SampleTestApplication执行run方法(这里我选的是这个启动类)。

启动项目

  • 报错 Kotlin: Language version 1.1 is no longer supported; please, use version 1.2 or greater.

    • 解决方式 image.png

    • 可能和idea版本有关系 我报了这个错 然后勾选idea这个选项就好了

    image.png

    • 注意其会有代码格式检查 需要关掉 在properties标签中加入 true
    • 或者格式化下代码 mvn spring-javaformat:apply

2. SpringBoot main方法执行过程详解

注意:(由于一边调试一边写注释的话 debug会错位 造成调试不便 所以我在另一个项目中调试的源码版本都一样)

1. 启动run();方法

```java @SpringBootApplication public class SampleTestApplication {

// NOTE: this application will intentionally not start without MySQL, the test will // still run. // 启动入口 public static void main(String[] args) { SpringApplication.run(SampleTestApplication.class, args); }

} ```

2. 进入SpringApplication的构造方法

主要包含两个 1.上下文初始化对象 2.监听器对象

```java /** * 创建一个新的 {@link SpringApplication} 实例。该应用程序上下文将从指定的primarySources加载 bean * (有关详细信息,请参阅 {@link SpringApplication class-level} 文档。可以在调用之前自定义实例 * {@link #run(String...)}. * @param resourceLoader the resource loader to use * @param primarySources the primary bean sources * @see #run(Class, String[]) * @see #setSources(Set) * * -- 在该构造中 将创建上下文对象 * */

@SuppressWarnings({ "unchecked", "rawtypes" }) public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) { //初始化资源加载器,默认为null this.resourceLoader = resourceLoader; //校验 Assert.notNull(primarySources, "PrimarySources must not be null"); //初始化 primarySources 类并去重 一般我们就是一个即启动类 this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); //推断当前 WEB 应用类型,一共有三种:NONE,SERVLET,REACTIVE 默认SERVLET this.webApplicationType = WebApplicationType.deduceFromClasspath();

// <2.1> 设置应用上下文初始化器,从META-INF/spring.factories读取 ApplicationContextInitializer类对应的实例名称集合并去重(一共6个) 随后 利用反射工具进行对象的创建

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

// <2.2> 设置监听器,从META-INF/spring.factories 读取ApplicationListener类的实例名称集合并去重。然后反射创建对象 其实和2.1过程很相似 唯一区别是 传入的参数 不同 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

//推断主入口应用类,通过当前调用栈,获取Main方法所在类,并赋值给mainApplicationClass this.mainApplicationClass = deduceMainApplicationClass(); } ```

## 紧接着我们看下 <2.1> 处做了什么

image.png

image.png 可以看到其用的系统类加载器 关于类加载器 可聊得就太多了 这里不做展开了

image.png

image.png

image.png - 接着使用 private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader)方法获取该类加载器下的所有spring.factories文件 名称 注意是名称还没到创建对象呢

```java private static Map > loadSpringFactories(@Nullable ClassLoader classLoader) { //根据类加载器先看看有没有 有直接返回 其实大部分情况都有 只有第一次调用该方法 也就是 构造SpringApplication上下文时候 需要加载当前包以及子包下的spring.factories文件 MultiValueMap result = (MultiValueMap)cache.get(classLoader); if (result != null) { return result; } else { try { //获取当前类加载器下的所有META-INF/spring.factories文件 Enumeration urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); LinkedMultiValueMap result = new LinkedMultiValueMap(); //遍历properties 取出对饮的value 文件 while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); //这里的url我理解就是 文spring.factoies文件的全路径 事实也是这样的 UrlResource resource = new UrlResource(url); //根据文件的全路径 加载文件中的数据 Properties properties = PropertiesLoaderUtils.loadProperties(resource);

Iterator var6 = properties.entrySet().iterator();
                //遍历某个spring.factory.properties文件  
                while(var6.hasNext()) {
                    Entry<?, ?> entry = (Entry)var6.next();
                    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值