SpringBoot判断该应用是已那种方式启动
WebApplicationType webApplicationType = REACTIVE/NONE/SERVLET;
/*
REACTIVE:Jar包存在DispatcherHandler并且不存在DispatcherServlet和ServletContainer则为响应式web应用;内嵌的响应式web服务
NONE:Jar包不存在Servlet和ConfigurableWebApplicationContext则为普通应用程序;不启动内嵌的服务
SERVLET :其他情况则为基于servlet的web应用,需加载并启动内嵌的web web服务;内嵌servlet web服务
*/
static WebApplicationType deduceFromClasspath() {
//isPresent底层是通过Class.forName()是否异常来判断
if (ClassUtils.isPresent("DispatcherHandler", null) && !ClassUtils.isPresent("DispatcherServlet", null)
&& !ClassUtils.isPresent("ServletContainer", null)) {
return WebApplicationType.REACTIVE;
}
for (String className : "Servlet,ConfigurableWebApplicationContext") {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
根据ClassLoader获取SpringFactoriesLoader.cache里的数据
如果数据为空默认获取 spring.factories 配置文件中的所有配置类,放入SpringFactoriesLoader.cache
static final Map<ClassLoader, Map<String, List<String>>> cache = new ConcurrentReferenceHashMap<>();
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = cache.get(classLoader);
if (result != null) {
return result;
}
result = new HashMap<>();
try {
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
String[] factoryImplementationNames =
StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
for (String factoryImplementationName : factoryImplementationNames) {
result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
.add(factoryImplementationName.trim());
}
}
}
// Replace all lists with unmodifiable lists containing unique elements
result.replaceAll((factoryType, implementations) -> implementations.stream().distinct()
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
cache.put(classLoader, result);
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
return result;
}
从SpringFactoriesLoader.cache获取key为ApplicationContextInitializer所有value类并通过反射执行,并放入->List<ApplicationContextInitializer<?>> initializers;
从SpringFactoriesLoader.cache获取key为ApplicationListener所有value类并通过反射执行,并放入->List<ApplicationListener<?>> listeners;;
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList<>(names.size());
for (String name : names) {
try {
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
T instance = (T) BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
}
}
return instances;
}
通过堆栈获取启动类并赋值给->Class<?> 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;
}