SpringApplication执行流程

SpringApplication类的直接作用是在main方法中通过自有的run方法启动spring应用。

具体的run方法为:

public static ConfigurableApplicationContext run(Object source, String... args)

该方法最终会把source传给SpringApplication的构造方法中的初始化方法:

private void initialize(Object[] sources) {

   if (sources != null && sources.length > 0) {

      this.sources.addAll(Arrays.asList(sources));

   }

   this.webEnvironment = deduceWebEnvironment();

   setInitializers((Collection) getSpringFactoriesInstances(

         ApplicationContextInitializer.class));

   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

   this.mainApplicationClass = deduceMainApplicationClass();

}

该初始化方法一共做了以下几件事:

一、判断sourse长度

首先,如果sources长度大于0(即是数组或容器),则把这些sources全部传到内置的hashset中。由此可见,run方法的第一个参数中是可以传入多个source的。

 

二、判断web环境是否正确

this.webEnvironment = deduceWebEnvironment();

判断整个环境中是否存在javax.servlet.Servlet类和

org.springframework.web.context.ConfigurableWebApplicationContext类这两个类,如果存在话,则表示web环境正常,返回true,否则返回false。

 

三、设置Initializers

首先会调getSpringFactoriesInstances方法加载ApplicationContextInitializer类,这个方法最终会运行SpringFactoriesLoader.loadFactoryNames方法,这个方法的目的是从“META-INF/spring.factories文件”中加载配置。

可实际上我们一般在开发springboot项目时并没有创建过spring.factories文件,可还是自动加载了各种配置,原因如下:

在项目的main方法上一般都会设置@SpringBootApplication注解,@SpringBootApplication注解中包含了多个注解,其中有一个@EnableAutoConfiguration注解尤为重要。

通过@EnableAutoConfiguration注解会将org.springframework.boot.autoconfigure.EnableAutoConfiguration这个包作为查找META-INF/spring.factories文件的根目录,即spring.factories文件会从org.springframework.boot.autoconfigure.EnableAutoConfiguration包中查找。而这个包里面自然有已经写好的spring.factories文件了。

整个springboot中会看到很多@Enable开头的注解,所有的@Enable开头的注解的作用都是通过@Import将“特定的bean”加载到Ioc容器中。@EnableAutoConfiguration的作用就是通过SpringFactoriesLoader将所有的标注了@Configuration注解的类加载(既有boot.autoconfigure包自带的标注了@Configuration的类,也可以是自己创建的标注了@Configration的类,都会被作为配置加载)

 

四、设置Listeners

listener的加载与之前的Initializers加载同理,都是寻找META-INF/spring.factories文件,然后被@EnableAutoConfiguration注解把路径转移到了org.springframework.boot.autoconfigure.EnableAutoConfiguration/META-INF/spring.factories中,之后就能找到已经提前写好的相关监听配置了。

 

五、设置mainApplicationClass

private Class<?> deduceMainApplicationClass() {

   try {

      StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();

      for (StackTraceElement stackTraceElement : stackTrace) {

         if ("main".equals(stackTraceElement.getMethodName())) {

            return Class.forName(stackTraceElement.getClassName());

         }

      }

   }

   catch (ClassNotFoundException ex) {

      // Swallow and continue

   }

   return null;

}

该方法是通过遍历栈,找到main方法,从而找到启动类,并将其赋值给mainApplicationClass属性。

 

posted @ 2018-07-05 10:46  Red_Code  阅读(4626)  评论(0编辑  收藏  举报