Spring Boot源码剖析系列(1) - 启动

写好一个启动类,Application,然后通过Spring Boot将它启动:

顺流而下, SpringApplication.run(): 从上面的run方法看到,启动类将会作为SpringApplication的构造函数的参数,而main方法的参数将会作为run方法的参数。

我们再来看SpringApplication的构造函数: initialize方法,一看名字就知道不一般,我们来仔细分析一下初始化了么。它首先是把启动类加到sources里,
接着判断是否是为web environment,调用了deduceWebEnvironment方法: 它是到classpath里面是否有javax.servlet.Servletorg.springframework.web.context.ConfigurableWebApplicationContext这两个类,只有这两个类都存在,才会认为这是web environment。 接着就是去查找initializerlistener,分别是接口ApplicationContextInitializerApplicationListener的实现类,都是通过调用getSpringFactoriesInstances方法: getSpringFactoriesInstance方法又是通过调用org.springframework.core.io.support.SpringFactoriesLoaderloadFactoryNames方法: loadFactoryNames方法是到classpath里查找出含有META-INF/spring.factories这个文件的jar包,然后将这个文件加载进来,读取里面的内容:
这一步其实跟我们常见的SPI方式是一样的。在spring-boot这个jar里,就有META-INF这个目录及spring.factories这个文件,该文件截取如下: 找到ApplicationContextInitializerApplicationListener的实现类后,就会通过调用SpringApplicationcreateSpringFactoriesInstances方法来创建它们的实例: 然后再通过set方法将initializerlistener注册上: 接着会推演出启动类,通过调用deduceMainApplicationClass方法,这个方法很特别,是通过遍历栈的信息,去查找被调用了main方法的类: 之所以说这个方法奇怪,是因为觉得它有点奇技淫巧的意思,我是从来没有想过还可以这样子来取得启动类:)

到此为止,SpringApplication类的初始化就结束了。我们接着来看它的run方法。 我们注意到它调用了getRunListeners这个方法取得一个SpringApplicationRunListeners,然后再starting它: 我们可以看到它也是像上文的ApplicationInitializerApplicationListener那样,通过spring.factories文件配置: 我们可以看到实际上是对上文中注册的所有ApplicationListener,都调用onApplicationEvent这个方法,参数为一个ApplicationStartedEvent.

我们继续往下看run方法,它会去调用createApplicationContext方法来创建ApplicationContext 根据上文的deduceWebEnvironment方法,如果classpath里面是否有javax.servlet.Servletorg.springframework.web.context.ConfigurableWebApplicationContext这两个类,只有这两个类都存在,那么webEnvironment则为true,那么将会去加载DEFAULT_WEB_CONZTEXT_CLASS,并创建它的实例: 然后prepareContextrefreshContext,这个两个方法都是最基本的初始化Spring容器的方法。接着它会调用afterRefresh方法,这个方法很重要: 我们可以看到它会去上文初始化好的Sprint容器中,查找出所有实现了ApplicationRunner和CommanLineRunner的java对象,然后调用他们的run的方法: 所以,如果你想在SpringBoot里面起启动另外一个服务,比如RPC服务,就可以通过这种方式来启动。

到此,Spring Boot的启动分析完毕。其实里面还有很多细节值得更加深入去剖析的。但这里的空白处实在太小,我写不下去了:)

留待下一篇继续!

Written on 20 August 2017