SpringBoot2.0之SpringApplication源码分析

此源码分析针对于SpringBoot的2.0.1.RELEASE版本

一、首先我们先看到启动类中

SpringBoot2.0之SpringApplication源码分析_第1张图片

二、点击进入SpringApplication的run方法

SpringBoot2.0之SpringApplication源码分析_第2张图片
由此可以看出SpringApplication.run(AppWeiXin.class, args);实际上是返回的有对象的。即ConfigurableApplicationContext

三、继续进入run方法

SpringBoot2.0之SpringApplication源码分析_第3张图片
由此我们可以知道

ConfigurableApplicationContext run = SpringApplication.run(AppWeiXin.class, args);
//其实就等于
ConfigurableApplicationContext run = new SpringApplication(AppWeiXin.class).run(args);
四、继续进入SpringApplication

SpringBoot2.0之SpringApplication源码分析_第4张图片
可以知道,SpringApplication的有参构造方法再次调用了它的重载有参构造方法

五、然后我们看到上面大红框中的this.webApplicationType = deduceWebApplicationType();,进入deduceWebApplicationType方法

SpringBoot2.0之SpringApplication源码分析_第5张图片
点击进入ClassUtil.isPresent方法中,同时进入REACTIVE_WEB_ENVIRONMENT_CLASS等几个常量中,我们可以知道deduceWebApplicationType就是判断是否为web应用,通过classLoader判断是否加载的有以下三个类

	public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframework."
			+ "boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext";

	private static final String REACTIVE_WEB_ENVIRONMENT_CLASS = "org.springframework."
			+ "web.reactive.DispatcherHandler";

	private static final String MVC_WEB_ENVIRONMENT_CLASS = "org.springframework."
			+ "web.servlet.DispatcherServlet";

然后我进入WebApplicationType中,看到NONE,SERVLET,REACTIVE三种枚举常量,查看官方文档官方文档可知:
SpringBoot2.0之SpringApplication源码分析_第6张图片

六、看到四中的setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class));

我们可以先看(Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class),它其实就是从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;然后再将其保存到List>中
SpringBoot2.0之SpringApplication源码分析_第7张图片
SpringBoot2.0之SpringApplication源码分析_第8张图片
SpringBoot2.0之SpringApplication源码分析_第9张图片
SpringBoot2.0之SpringApplication源码分析_第10张图片

七、看到四中的setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));,原理同六

它是从类路径下找到META-INF/spring.factories配置的所有ApplicationListener

八、然后获取Main函数主类
this.mainApplicationClass = deduceMainApplicationClass();
九、SpringBoot的run方法说明
public ConfigurableApplicationContext run(String... args) {
     
 // 构造一个任务执行观察器
   StopWatch stopWatch = new StopWatch();
// 开始执行,记录开始时间
   stopWatch.start();
// 声明IOC容器
   ConfigurableApplicationContext context = null;
   Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
   configureHeadlessProperty();
// 获取SpringApplicationRunListeners,内部只有一个EventPublishingRunListener
   SpringApplicationRunListeners listeners = getRunListeners(args);
    //回调所有的获取SpringApplicationRunListener.starting()方法
 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, listeners, exceptionReporters, ex);
      throw new IllegalStateException(ex);
   }
   listeners.running(context);
   return context;
}

你可能感兴趣的:(源码分析,Java,Java源码分析及手写,SpringBoot源码分析,源码分析)