SpringBoot原始碼解析建立SpringApplication物件例項
阿新 • • 發佈:2021-12-05
上篇文章中的main方法來分析SpringApplication
這個類
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
點選run
方法一路跟蹤下來,發現首先做的是例項化SpringApplication
物件例項
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
- 載入所有的
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
註解的值進行排序
關於這些實現類的具體作用請關注後續的文章
- 最後一行的意義是找到入口方法main所在的類,賦值給全域性變數
mainApplicationClass