复制
- 若满足类路径(包括依赖jar包)中存在
org.springframework.web.reactive.DispatcherHandler
类 , 同时不存在org.springframework.web.servlet.DispatcherServlet
类和org.glassfish.jersey.servlet.ServletContainer
类则返回REACTIVE类型Web应用 - 遍历判断类路径中是否同时存在
javax.servlet.Servlet
类和org.springframework.web.context.ConfigurableWebApplicationContext
类,满足则返回SERVLET类型Web应用,否则返回非Web应用
SpringApplication#getSpringFactoriesInstances
方法得到的返回值设置初始化器和监听器属性,传入的参数分别为ApplicationContextInitializer
类和ApplicationListener
类/***根据传入的type参数获取类路径META-INF/spring.factories文件中的自动配置初始化类集合@param type 类型@return Collection<T> 泛型集合*/private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {return this.getSpringFactoriesInstances(type, new Class[0]);}/***上一个方法的多参数重载方法* @param type 类型* @param parameterTypes 参数类型数组* @param args 参数数组*/private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = this.getClassLoader();// 通过SpringFactoriesLoader#loadFactoryNames方法获取Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances;}public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {String factoryClassName = factoryClass.getName();return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());}private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {// 如果缓存里有则直接从双层缓存中获取类加载器对应的结果MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);if (result != null) {return result;} else {// 缓存中没有则去META-INF/spring.factories文件中加载并读取解析try {Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");LinkedMultiValueMap result = new LinkedMultiValueMap();while(urls.hasMoreElements()) {URL url = (URL)urls.nextElement();UrlResource resource = new UrlResource(url);Properties properties = PropertiesLoaderUtils.loadProperties(resource);Iterator var6 = properties.entrySet().iterator();while(var6.hasNext()) {Entry<?, ?> entry = (Entry)var6.next();String factoryClassName = ((String)entry.getKey()).trim();String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());int var10 = var9.length;for(int var11 = 0; var11 < var10; ++var11) {String factoryName = var9[var11];result.add(factoryClassName, factoryName.trim());}}}cache.put(classLoader, result);return result;} catch (IOException var13) {throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);}}}/*** 创建spring.factories文件中的初始化类实例集合*/private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) {List<T> instances = new ArrayList(names.size());Iterator var7 = names.iterator();while(var7.hasNext()) {String name = (String)var7.next();try {// 调用反射工具类加载spring.factories文件中的初始化类Class<?> instanceClass = ClassUtils.forName(name, classLoader);Assert.isAssignable(type, instanceClass);Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);// 通过构造函数实例化类T instance = BeanUtils.instantiateClass(constructor, args);instances.add(instance);} catch (Throwable var12) {throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, var12);}}return instances;}
复制推断主应用类
private Class<?> deduceMainApplicationClass() {try {StackTraceElement[] stackTrace = (new RuntimeException()).getStackTrace();StackTraceElement[] var2 = stackTrace;int var3 = stackTrace.length;for(int var4 = 0; var4 < var3; ++var4) {StackTraceElement stackTraceElement = var2[var4];if ("main".equals(stackTraceElement.getMethodName())) {return Class.forName(stackTraceElement.getClassName());}}} catch (ClassNotFoundException var6) {}return null;}
复制通过上面的源码我们可以看到推断主应用类是通过实例化一个运行时异常,并拿到该运行时异常的堆栈数组,然后循环遍历堆栈数组,判断堆栈元素的方法名是否为
推荐阅读
- 一次SpringBoot版本升级,引发的血案
- SpringBoot 03: 常用web组件 - - - 拦截器 + Servlet + 过滤器
- SpringBoot 02: 初识SpringBoot
- 超详细 SpringBoot 整合 Elasticsearch .md
- SpringBoot 01: JavaConfig + @ImportResource + @PropertyResource
- MindStudio模型训练场景精度比对全流程和结果分析
- 纸嫁衣4第三章交错通关流程图文攻略
- 纸嫁衣4第一章异途通关流程图文攻略-纸嫁衣4红丝缠第一章怎么过
- 纸嫁衣4第二章不期通关流程图文攻略-纸嫁衣4红丝缠第二章怎么过
- 洛克王国初秋落叶活动流程攻略-洛克王国初秋落叶怎么玩