从哪入手?

相信很多人尝试读过Spring Boot的源码,但是始终没有找到合适的方法。那是因为你对Spring Boot的各个组件、机制不是很了解,研究起来就像大海捞针。

至于从哪入手不是很简单的问题吗,当然主启动类了,即是标注着@SpringBootApplication注解并且有着main()方法的类,如下一段代码:

@SpringBootApplication
public class AnnotationDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(AnnotationDemoApplication.class, args);
    }
}

源码如何切分?

SpringApplication中的静态run()方法并不是一步完成的,最终执行的源码如下:

//org.springframework.context.ConfigurableApplicationContext
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
  return new SpringApplication(primarySources).run(args);
 }

如何创建SpringApplication?

创建即是new对象了,DEBUG跟进代码,最终执行的SpringApplication构造方法如下图:

springboot ppt在线查看 怎么快速看懂springboot代码_spring

设置应用类型

这个过程非常重要,直接决定了项目的类型,应用类型分为三种,都在WebApplicationType这个枚举类中,如下:

  1. NONE:顾名思义,什么都没有,正常流程走,不额外的启动web容器,比如Tomcat
  2. SERVLET:基于servlet的web程序,需要启动内嵌的servletweb容器,比如Tomcat
  3. REACTIVE:基于reactive的web程序,需要启动内嵌reactiveweb容器,作者不是很了解,不便多说。

判断的依据很简单,就是加载对应的类,比如加载了DispatcherServlet等则会判断是Servlet的web程序。源码如下:

static WebApplicationType deduceFromClasspath() {
  if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
    && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
   return WebApplicationType.REACTIVE;
  }
  for (String className : SERVLET_INDICATOR_CLASSES) {
   if (!ClassUtils.isPresent(className, null)) {
    return WebApplicationType.NONE;
   }
  }
  return WebApplicationType.SERVLET;
 }

这里我引入了spring-boot-starter-web,肯定是Servlet的web程序。

设置初始化器(Initializer)

初始化器ApplicationContextInitializer是个好东西,用于IOC容器刷新之前初始化一些组件,比如ServletContextApplicationContextInitializer

那么如何获取初始化器呢?跟着上图中的代码进入,在SpringApplication中的如下图中的方法:

springboot ppt在线查看 怎么快速看懂springboot代码_初始化_02

相对重要的就是第一步获取初始化器的名称了,这个肯定是全类名了,详细源码肯定在loadFactoryNames()方法中了,跟着源码进入,最终调用的是#SpringFactoriesLoader.loadSpringFactories()方法。

loadSpringFactories()方法就不再详细解释了,其实就是从类路径META-INF/spring.factories中加载ApplicationContextInitializer的值。

设置监听器(Listener)

监听器(ApplicationListener)这个概念在Spring中就已经存在,主要用于监听特定的事件(ApplicationEvent),比如IOC容器刷新、容器关闭等。

Spring Boot扩展了ApplicationEvent构建了SpringApplicationEvent这个抽象类,主要用于Spring Boot启动过程中触发的事件,比如程序启动中、程序启动完成等。

监听器如何获取?从源码中知道其实和初始化器(ApplicationContextInitializer)执行的是同一个方法,同样是从META-INF/spring.factories文件中获取。

总结

SpringApplication的构建都是为了run()方法启动做铺垫,构造方法中总共就有几行代码,最重要的部分就是设置应用类型、设置初始化器、设置监听器。