成员的初始化
private Set<String> sources = new LinkedHashSet<>();
private Banner.Mode bannerMode = Banner.Mode.CONSOLE;
private boolean logStartupInfo = true;
private boolean addCommandLineProperties = true;
private boolean addConversionService = true;
private boolean headless = true;
private boolean registerShutdownHook = true;
private Set<String> additionalProfiles = Collections.emptySet();
private boolean isCustomEnvironment = false;
private boolean lazyInitialization = false;
// ApplicationContextFactory.DEFAULT
private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;
// ApplicationStartup.DEFAULT
private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT;
构造方法的初始化
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader; // null
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); // primarySources 启动类传进来的
// 推断程序类型,通过检查有没有特定的实现类来确定
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 在 MATE-INF/spring.factory 中查找 BootstrapRegistryInitializer 实现,放到成员变量中
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
// ApplicationContextInitializer 同上
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// ApplicationListener 同上
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 通过栈信息推断启动类,须要注意:和 primarySources 的实现方式是不一样的
this.mainApplicationClass = deduceMainApplicationClass();
}
WebApplicationType 推断
/**
String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext" };
WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";
WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";
JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
*/
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
ApplicationContextFactory.DEFAULT 是什么
一个 ConfigurableApplicationContext 的创建工厂,根据 application 的类型 WebApplicationType{NONE,SERVLET, REACTIVE } 来创建不同的应用,其具体实现有:
// 默认的,可创建 AnnotationConfigApplicationContext
org.springframework.boot.DefaultApplicationContextFactory;
// AnnotationConfigReactiveWebServerApplicationContext 的静态内部类,用于创建 AnnotationConfigReactiveWebServerApplicationContext
org.springframework.boot.ApplicationContextFactory;
// AnnotationConfigServletWebServerApplicationContext 的静态内部类,用于创建 AnnotationConfigServletWebServerApplicationContext
org.springframework.boot.ApplicationContextFactory;
ApplicationStartup.DEFAULT 是什么?
The core container and its infrastructure components can use the ApplicationStartup to mark steps during the application startup and collect data about the execution context or their processing time.
貌似没有核心用途。
getSpringFactoriesInstances(Class type) 方法
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// SpringFactoriesLoader.loadFactoryNames(type, classLoader) 读 META-INF/spring.factories 获取相应的类
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader)
);
// createSpringFactoriesInstances(...) 根据上一步的结果,实例化类对象
List<T> instances = createSpringFactoriesInstances(
type, parameterTypes, classLoader, args, names
);
// 根据 Order 排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}