学习spring这个框架,我们总是有种感觉,会用但是不懂,“会用”是因为spring的框架利用约定大于配置的原则帮我们封装好了所有的启动配置类,这样我们使用起来的入门门槛就比较低了,只要照着官方的文档配置,一般都不会有问题,“不懂”是因为我们不知道他的底层到底是怎么实现的,有种雾里看花的感觉,一旦我们想拓展下spring的框架,就无从下手了, spring作为一个优秀的开源框架,我们很有必要去探究下他的底层实现,同时作为一名程序员,知其然也要知其所以然,要有求知欲望,这样才能站得高看的远,废话不多说,今天我们就来详细剖析下spring的启动过程(文中可能有错误的地方,希望各位看官能及时指出,非常感谢):
先看一个spring启动的例子:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class,args);
}
}
只要这一行启动代码,spring就为我们默认配置好了一切项目运行所必须的环境,是不是很简单,就从这里入手,看看spring到底做了什么!
public static ConfigurableApplicationContext run(Object source, String... args) {
return run(new Object[]{source}, args);
}
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
//调用springApplication的构造函数
return (new SpringApplication(sources)).run(args);
}
public SpringApplication(Object... sources) {
//创建一个新的SpringApplication对象
initialize(sources);
}
private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
//判断是不是一个web的应用,判断的逻辑是加载 "javax.servlet.Servlet",
//"org.springframework.web.context.ConfigurableWebApplicationContext"这两个类,如果加载成功,则是web应用
// this.webEnvironment = true
this.webEnvironment = deduceWebEnvironment();
//初始化各种初始化器的实例,这些势力将会在创建好ApplicationContext后,prepare时进行调用,这里只是先对其进行实例化设值;
//这里总共有6个Initializers,是从spring.factories配置文件里面读取到的
//0 = {DelegatingApplicationContextInitializer@2208}
//1 = {ContextIdApplicationContextInitializer@2209}
//2 = {ConfigurationWarningsApplicationContextInitializer@2210}
//3 = {ServerPortInfoApplicationContextInitializer@2211}
//4 = {SharedMetadataReaderFactoryContextInitializer@2212}
//5 = {AutoConfigurationReportLoggingInitializer@2213}
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
//设置10个listeners,实现原理同上,这里就不再赘述了,找到所有实现了ApplicationListener接口的实现类并实例化
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//从堆栈中找到启动类的信息并加载启动类,这里就是加载Application类,到这里,初始化的工作基本完成,下面开始执行Application //的run方法
this.mainApplicationClass = deduceMainApplicationClass();
}
public ConfigurableApplicationContext run(String... args) {
//new一个执行时间的监视器,记录spring启动的开始、结束时间;
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
//设置system的java.awt.headless的属性
this.configureHeadlessProperty();
//初始化一个SpringApplicationRunListeners对象,里面包含SpringApplicationRunListener数组,这里的数组只有一个监听器
//对象EventPublishingRunListener,他会发布一个ApplicationStartedEvent事件,我们可以监听这个事件做一些初始化的工作,
//其初始化SpringApplicationRunListener的实现原理同上面的ApplicationListener
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//因为是一个web应用,所以这里初始化一