上篇文章SpringBoot自動裝配原理解析中,咱們分析了SpringBoot的自動裝配原理以及
@SpringBootApplication
註解的原理,本篇文章則繼續基於上篇文章中的main方法來分析SpringApplication
這個類java
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}複製代碼
點擊run
方法一路跟蹤下來,發現首先作的是實例化SpringApplication
對象實例react
public static ConfigurableApplicationContext run(Class<?> primarySource,
String... args) {
return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources,
String[] args) {
return new SpringApplication(primarySources).run(args);
}
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = deduceWebApplicationType();
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}複製代碼
deduceWebApplicationType
方法 private WebApplicationType deduceWebApplicationType() {
if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null)) {
return WebApplicationType.REACTIVE;
}
for (String className : "javax.servlet.Servlet", org.springframework.web.context.ConfigurableWebApplicationContext") {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
}複製代碼
大抵意思就是根據當前項目中是否存在上方的幾個類來推斷出當前的web環境,這裏由於SpringBoot默認使用的web框架是SpringMVC,因此最後返回結果爲WebApplicationType.SERVLET
web
ApplicationContextInitializer
和ApplicationListener
的實現類 private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}複製代碼
能夠看到主要仍是用的SpringFactoriesLoader
這個類去加載這兩個接口的實現類,加載到類之後使用反射的方式構造出這些類的實例,而後根據這些實現類上的Order
註解的值進行排序spring
關於這些實現類的具體做用請關注後續的文章框架
mainApplicationClass