前面介绍了SpringBoot
的启动流程,接下来分析启动流程中的细节,首先是启动时对应用类型的判断
1. SpringBoot
中的应用类型介绍
打开WebApplicationType
枚举,可以看到SpringBoot
中共有三种应用类型
public enum WebApplicationType {
//应用程序不应作为Web应用程序运行,也不应启动嵌入式Web服务器。
NONE,
//应用程序应作为基于servlet的Web应用程序运行,并应启动嵌入式servlet Web服务器。
SERVLET,
//应用程序应作为响应式Web应用程序运行,并应启动嵌入式响应式Web服务器。
REACTIVE
}
接上文02--SpringBoot启动源码简单分析创建SpringApplication
实例中
this.webApplicationType = deduceWebApplicationType();
2. 推断SpringBoot
中的应用类型
//推断应用类型
private WebApplicationType deduceWebApplicationType() {
//REACTIVE_WEB_ENVIRONMENT_CLASS可加载且MVC_WEB_ENVIRONMENT_CLASS和JERSEY_WEB_ENVIRONMENT_CLASS不能加载,则为响应式web应用
if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null)
&& !ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_WEB_ENVIRONMENT_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
//Servlet和ConfigurableWebApplicationContext不能加载则为非web应用类型
for (String className : WEB_ENVIRONMENT_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
//排除上述两种类型,推断当前应用为servlet类型
return WebApplicationType.SERVLET;
}
//isPresent判断的类型如下
private static final String REACTIVE_WEB_ENVIRONMENT_CLASS = "org.springframework.web.reactive.DispatcherHandler";
private static final String MVC_WEB_ENVIRONMENT_CLASS = "org.springframework.web.servlet.DispatcherServlet";
private static final String JERSEY_WEB_ENVIRONMENT_CLASS = "org.glassfish.jersey.server.ResourceConfig";
private static final String[] WEB_ENVIRONMENT_CLASSES = {"javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"};
ClassUtils.java
是org.springframework.util
下的工具类,不是JDK
的工具类,我们来看其中的
isPresent()
方法
//判断className类是否存在且可以被加载
public static boolean isPresent(String className, @Nullable ClassLoader classLoader) {
try {
//如果className可以被加载,返回true
forName(className, classLoader);
return true;
}
catch (IllegalAccessError err) {
throw new IllegalStateException("Readability mismatch in inheritance hierarchy of class [" +className + "]: " + err.getMessage(), err);
}
catch (Throwable ex) {
// Typically ClassNotFoundException or NoClassDefFoundError...
//className加载失败,返回false
return false;
}
}
分析forName(className, classLoader);
方法
/**
替换Class.forName()它也会返回基元的类实例(例如“int”)和数组类名(例如“String []”)。
此外,它还能够以Java源代码样式解析内部类名(例如“java.lang.Thread.State”而不
是“java.lang.Thread $ State”)。
如果找不到或者无法加载类则抛出异常
*/
public static Class<?> forName(String name, @Nullable ClassLoader classLoader) throws ClassNotFoundException, LinkageError {
Assert.notNull(name, "Name must not be null");
//根据JVM的基本类命名规则,将给定的类名解析为基本类(如果适用)。
Class<?> clazz = resolvePrimitiveClassName(name);
//从commonClassCache缓存Map中获取,如果存在则返回
if (clazz == null) {
clazz = commonClassCache.get(name);
}
if (clazz != null) {
return clazz;
}
// "java.lang.String[]" style arrays
if (name.endsWith(ARRAY_SUFFIX)) {
String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length());
Class<?> elementClass = forName(elementClassName, classLoader);
return Array.newInstance(elementClass, 0).getClass();
}
// "[Ljava.lang.String;" style arrays
if (name.startsWith(NON_PRIMITIVE_ARRAY_PREFIX) && name.endsWith(";")) {
String elementName = name.substring(NON_PRIMITIVE_ARRAY_PREFIX.length(), name.length() - 1);
Class<?> elementClass = forName(elementName, classLoader);
return Array.newInstance(elementClass, 0).getClass();
}
// "[[I" or "[[Ljava.lang.String;" style arrays
if (name.startsWith(INTERNAL_ARRAY_PREFIX)) {
String elementName = name.substring(INTERNAL_ARRAY_PREFIX.length());
Class<?> elementClass = forName(elementName, classLoader);
return Array.newInstance(elementClass, 0).getClass();
}
//获取ClassLoader
ClassLoader clToUse = classLoader;
if (clToUse == null) {
clToUse = getDefaultClassLoader();
}
try {
//如果ClassLoader不为空则使用ClassLoader加载类,否则使用Class类来加载类
return (clToUse != null ? clToUse.loadClass(name) : Class.forName(name));
}
catch (ClassNotFoundException ex) {
int lastDotIndex = name.lastIndexOf(PACKAGE_SEPARATOR);
if (lastDotIndex != -1) {
String innerClassName = name.substring(0, lastDotIndex) + INNER_CLASS_SEPARATOR + name.substring(lastDotIndex + 1);
try {
return (clToUse != null ? clToUse.loadClass(innerClassName) : Class.forName(innerClassName));
}
catch (ClassNotFoundException ex2) {
// Swallow - let original exception get through
}
}
throw ex;
}
}
//获取ClassLoader
public static ClassLoader getDefaultClassLoader() {
ClassLoader cl = null;
try {
//首先尝试获得线程上下文类加载器
cl = Thread.currentThread().getContextClassLoader();
}
catch (Throwable ex) {
// Cannot access thread context ClassLoader - falling back...
}
if (cl == null) {
//如果没有获取到线程上下文类加载器,则使用当前类的类加载器
cl = ClassUtils.class.getClassLoader();
if (cl == null) {
// getClassLoader() returning null indicates the bootstrap ClassLoader
try {
//如果当前类的类加载器也没有获取到,则使用bootstrap ClassLoader
cl = ClassLoader.getSystemClassLoader();
}
catch (Throwable ex) {
// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
}
}
}
return cl;
}
通过上面的分析,我们就可以得出当前的应用的具体类型
网友评论