推断web应用类型通过加载类路径目录META-INF下的spring.factories
文件读取出初始化器和监听器集合并设置到SpringApplication
实例对应的初始化器和监听器属性列表中推断主启动类并赋值给SpringApplication
启动类的mainApplicationClass
属性推断Web应用类型进入
WebApplicationType#deduceFromClasspath
方法
private static final String[] SERVLET_INDICATOR_CLASSES = new String[]{"javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"};static WebApplicationType deduceFromClasspath() {if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) {return REACTIVE;} else {String[] var0 = SERVLET_INDICATOR_CLASSES;int var1 = var0.length;for(int var2 = 0; var2 < var1; ++var2) {String className = var0[var2];if (!ClassUtils.isPresent(className, (ClassLoader)null)) {return NONE;}}return SERVLET;}}
复制
- 若满足类路径(包括依赖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应用
加载spring.factories文件中配置的初始化器和监听器通过调用
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;}
经验总结扩展阅读
-
-
-
-
-
-
事业单位高温补贴多少钱 事业单位高温补贴发放是每年都有吗
-
28岁女白领:靠出轨38岁领导走向事业顶峰,我却过得很煎熬
-
-
卡西欧手表哪一款性价比高,卡西欧系列的手表都有哪些好的推荐?
-
-
-
久久说情感 凤凰男要求AA制,多年后却向妻子求助,妻子回应:我有钱,但不帮
-
-
-
-
-
-
-
-
连衣裙 炎热的夏天,穿一件短款修身连衣裙游逛商厦绝对是最惬意的事情!