上篇文章SpringBoot自动装配原理解析中,我们分析了SpringBoot的自动装配原理以及
@SpringBootApplication
注解的原理,本篇文章则继续基于上篇文章中的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 Collection getSpringFactoriesInstances(Class type, Class>[] parameterTypes, Object... args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Set names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
可以看到主要还是用的SpringFactoriesLoader
这个类去加载这两个接口的实现类,加载到类以后使用反射的方式构造出这些类的实例,然后根据这些实现类上的Order
注解的值进行排序
关于这些实现类的具体作用请关注后续的文章
- 最后一行的意义是找到入口方法main所在的类,赋值给全局变量
mainApplicationClass