SpringBoot源码分析------关键代码分析

本文深入剖析SpringBoot的`run()`方法,详细讲解了从启动、配置环境、创建ApplicationContext到加载配置文件、输出Banner、刷新上下文的全过程。在配置文件读取部分,解释了如何从不同路径和类型的配置文件中获取信息,并将其加载到SpringBoot项目中。最后,讨论了classpath与file路径读取配置文件的区别。
摘要由CSDN通过智能技术生成

我们在之前已经了解SpringBoot源码分析------mvc容器的创建和tomcat的启动过了,SpringBoot的启动是通过内部new出对象,在进行run()方法的。

现在我们来了解一下run()方法中的每一个步骤。

SpringApplication.run()

public ConfigurableApplicationContext run(String... args) {
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
	ConfigurableApplicationContext context = null;
	Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
	configureHeadlessProperty();
	SpringApplicationRunListeners listeners = getRunListeners(args);
	listeners.starting();
	try {
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
		ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
		configureIgnoreBeanInfo(environment);
		Banner printedBanner = printBanner(environment);
		context = createApplicationContext();
		exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
				new Class[] { ConfigurableApplicationContext.class }, context);
		prepareContext(context, environment, listeners, applicationArguments, printedBanner);
		refreshContext(context);
		afterRefresh(context, applicationArguments);
		stopWatch.stop();
		if (this.logStartupInfo) {
			new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
		}
		listeners.started(context);
		callRunners(context, applicationArguments);
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, exceptionReporters, listeners);
		throw new IllegalStateException(ex);
	}

	try {
		listeners.running(context);
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, exceptionReporters, null);
		throw new IllegalStateException(ex);
	}
	return context;
}
  1. Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); 声明IOC容器

  2. SpringApplicationRunListeners listeners = getRunListeners(args); 获取SpringApplicationRunListeners,内部只有一个EventPublishingRunListener,我们可以看看这个方法是执行的什么
    在这里插入图片描述
    想必都已经很熟悉这个getSpringFactoriesInstances()方法了,他就是读取META-INF/factories文件中的某个类,我们可以拿着SpringApplicationRunListener去springboot的包中搜索一下,可以发现只有一个
    在这里插入图片描述

  3. listeners.starting(); 回调所有的获取SpringApplicationRunListener.starting()方法
    目前我们没有自定义的SpringApplicationRunListener子类的方法,所以只有一个EventPublishingRunListener.starting()被回调。我们也可以看看内部的代码,就是一个for循环进行了回调
    在这里插入图片描述

  4. ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); 将args进行包装

  5. ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); 重点
    进入代码
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    这里可以看到只是进行了一些数据的初始化。再回到前面,看load()方法。
    在这里插入图片描述
    不是我说,包装的是真的多
    在这里插入图片描述
    在这里插入图片描述
    此处还有一个names,我们去查看一下getSearchNames()方法。
    在这里插入图片描述
    并且查看这个常量。
    在这里插入图片描述
    这里有个foreach,我们可以查看一下这个Lambda表达式具体什么意思。进去看看getSearchLocations()方法。
    在这里插入图片描述
    可以查看到DEFAULT_SEARCH_LOCATIONS这个常量的数据为
    在这里插入图片描述
    然而这个数据又是下面的参数location
    在这里插入图片描述
    在这里插入图片描述
    在这个方法中可以先看看loader、location、name这三个变量。
    1.loader
    在这里插入图片描述
    里面有着xml、yaml、yml、properties,这几个变量我们应该都很熟悉,这些都是配置文件的后缀。
    2.location
    上面已经提到过
    3.name
    上面已经提到过
    从这三个小点我们可以知道,默认读取的配置文件名为application,其中配置文件可以存在于classpath:/,classpath:/config/,file:./,file:./config/*/,file:./config/目录下,配置文件的类型可以为xml、yaml、yml、properties
    回到前面,继续看这一重重的封装
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    可以先提出来,在这一个方法中,开始获取到配置文件中的信息,并且马上要写入到springboot中。
    List<Document> documents = loadDocuments(loader, name, resource);此处获取配置文件中的信息。目前我的配置文件中只有一个数据
    在这里插入图片描述
    我们可以debug到这个位置。可以查看到此行代码运行后。
    在这里插入图片描述
    就已经拿到了数据。
    此处拿完数据之后就会回到
    在这里插入图片描述
    中的addLoadedPropertySources()方法,看看这个方法。
    在这里插入图片描述
    如果使用过Properties文件读取的朋友,应该很熟悉。这是将资源添加到项目中
    之后运行到addLoadedPropertySource(destination, lastAdded, source);这段代码。
    在这里插入图片描述
    将数据添加到SpringBoot项目中。至此。ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); 已经结束。

  6. Banner printedBanner = printBanner(environment); 输出SpringBoot的标志图标

  7. context = createApplicationContext();创建SpringBoot上下文

  8. refreshContext(context); 刷新上下文。这里面进行的就是tomcat的启动,加载springmvc
    我们前面的文章提到过这两个方法。可以在其中打上断点,查看一下它的调用链。
    在这里插入图片描述

  9. afterRefresh(context, applicationArguments); 定义一个空的模板方法给其他子类实现

  10. listeners.started(context); 使用广播和回调机制通知监听器SpringBoot容器启动成功

  11. listerens.running(context) 使用广播和回调机制通知监听器 SpringBoot容器启动成功并可执行其他的请求

  12. 返回当前上下文。

到这里就算结束了,是不是在读取配置文件那一部分很懵逼?懵逼就对了,等会来个简易版本的(SpringBoot源码分析------简易的配置文件读取),再回过头来看一遍就可以了解了。

在这之前,询问个问题。

classpath读取配置文件和file读取配置文件有什么区别?

classpath读取的配置文件是编译后的文件,而file的配置文件是没有经过编译的文件。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙小虬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值