要想用好springboot,不仅仅是知道怎么样用,而且要知道为啥这么用,他是怎么实现这么用的。。
计划写一些列阅读springboot源码的文章,写不写的完再说,反正有时间的话就多看看。
今天就以启动springboot开始来这一系列吧。
本文基于springboot-1.5.X系列
首先写把整体流程抛出来:
在
context
的refresh
方法中,需要注册bean definition
,实例化bean
.在加载bean defintion
的时候使用ConfigurationClassParser
类来解析我们的主类。然后在解析主类的时候发现了@EnableAutoConfiguratio
注解中的@Import
注解,就去处理@Import
注解中的value
值,然后就使用ImportSelector
来获取被配置在spring.factories
中的类。这些类通常是AutoConfiguration
。这些configuration
中包含了各种各样的bean
一般我们的springboot程序都会有个核心的类:
这里在main函数里调用了SpringApplication的静态函数run()方法。
到SpringApplication类里看看究竟发生了什么,可以看到如下的调用:
实例化SpringApplication, 通过调用initialize方法
这里调用了SpringApplication
的构造函数,然后执行run方法,构造函数和run方法分别为:
先设置 webEnvironment
webEnvironment
变量是一个boolean
类型的变量,通过名字猜测是用来判断是否application
是否为web程序,设置方法为:
再来设置成员变量Initializers
initialize
方法的代码中还调用了getSpringFactoriesInstances(ApplicationContextInitializer.class)
,来获取ApplicationContextInitializer
类型对象的列表。
|
|
在该方法中,首先通过调用SpringFactoriesLoader.loadFactoryNames(type, classLoader)
来获取所有Spring Factories
的名字,然后调用createSpringFactoriesInstances
方法根据读取到的名字创建对象。最后会将创建好的对象列表排序并返回。
|
|
可以看到,是从一个名字叫META-INF/spring.factories的资源文件中,读取key为org.springframework.context.ApplicationContextInitializer的value。而spring.factories的部分内容如下:
|
|
可以看到,最近的得到的,是
- ConfigurationWarningsApplicationContextInitializer,
- ContextIdApplicationContextInitializer,
- DelegatingApplicationContextInitializer,
- ServerPortInfoApplicationContextInitializer
这四个类的名字。
接下来会调用createSpringFactoriesInstances来创建ApplicationContextInitializer实例。
|
|
所以在我们的例子中,SpringApplication对象的成员变量initalizers就被初始化为,
- ConfigurationWarningsApplicationContextInitializer,
- ContextIdApplicationContextInitializer,
- DelegatingApplicationContextInitializer,
- ServerPortInfoApplicationContextInitializer
这四个类的对象组成的list。
下图画出了加载的ApplicationContextInitializer,并说明了他们的作用。
接下来是成员变量listeners
listeners成员变量,是一个ApplicationListener<?>类型对象的集合。可以看到获取该成员变量内容使用的是跟成员变量initializers一样的方法,只不过传入的类型从ApplicationContextInitializer.class变成了ApplicationListener.class。
同样也可以从META-INF/spring.factories中找到对应的定义,
也就是说,在我们的例子中,listener最终会被初始化为
- ClearCachesApplicationListener,
- ParentContextCloserApplicationListener,
- FileEncodingApplicationListener,
- AnsiOutputApplicationListener,
- ConfigFileApplicationListener,
- DelegatingApplicationListener,
- LiquibaseServiceLocatorApplicationListener,
- ClasspathLoggingApplicationListener,
- LoggingApplicationListener
这几个类的对象组成的list。
下图画出了加载的ApplicationListener,并说明了他们的作用。
最后是mainApplicationClass
|
|
在deduceMainApplicationClass方法中,通过获取当前调用栈,找到入口方法main所在的类,并将其复制给SpringApplication对象的成员变量mainApplicationClass。在我们的例子中mainApplicationClass即是我们自己编写的Application类:ZhuqiStudyPureSpringbootApplication
。
那么接下来就是执行run方法了。
这一部分我们留到下面的part2吧。