springboot中getSpringFactoriesInstances源码的示例分析
                                            这篇文章主要介绍了springboot中getSpringFactoriesInstances源码的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
网站建设哪家好,找创新互联公司!专注于网页设计、网站建设、微信开发、小程序定制开发、集团企业网站建设等服务项目。为回馈新老客户创新互联还提供了石泉免费建站欢迎大家使用!
一、概述及流程图
在springboot启动过程中,getSpringFactoriesInstances这个方法很重要,启动的时候使用该方法从classpath上所有jar包中找出对应的META-INF/spring.factorys属性文件,并将其中的初始化器和监听器加载并实例化,应用于更进一步的初始化工作。其工作流程图如下:
 
 
  二、源码解析
让我们跟着流程图和时序图一步步窥视其中的奥妙:
 
 
  
调用getSpringFactoriesInstances()方法 
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) {
 //资源加载器
 this.resourceLoader = resourceLoader;
 //断言,传入参数不能为空,即必须传入启动类
 Assert.notNull(primarySources, "PrimarySources must not be null");
 this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
 //通过类路径推断服务类型
 this.webApplicationType = WebApplicationType.deduceFromClasspath();
 //1.加载初始化器并实例化,10.并赋值给initializers
 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
 //同上,监听器
 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
 //推断应用主类
 this.mainApplicationClass = deduceMainApplicationClass();
}
获取类加载器和调用loadFactoryNames()方法及对返回结果进行初始化以及排序 
private  Collection getSpringFactoriesInstances(Class type) {
 return getSpringFactoriesInstances(type, new Class>[] {});
}
private  Collection getSpringFactoriesInstances(Class type, Class>[] parameterTypes, Object... args) {
 //2. 获取类加载器
 ClassLoader classLoader = getClassLoader();
 // Use names and ensure unique to protect against duplicates
 //3. 调用loadFactoryNames方法,并使用set对其返回结果进行去重处理
 Set names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
 //9. 实例化初始化器
 List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
 //9. 对实例化的结果进行排序
 AnnotationAwareOrderComparator.sort(instances);
 return instances;
}
//该方法主要是通过反射实例化初始化器
private  List createSpringFactoriesInstances(Class type, Class>[] parameterTypes,
   ClassLoader classLoader, Object[] args, Set names) {
  List 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;
 }
             
查询缓存和读取META-INFO/spring.factorys文件key-value值,并对value值进行处理 
public static List loadFactoryNames(Class> factoryClass, @Nullable ClassLoader classLoader) {
  String factoryClassName = factoryClass.getName();
  // 返回初始化器的value值
  return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
 }
 private static Map> loadSpringFactories(@Nullable ClassLoader classLoader) {
  MultiValueMap result = //查询缓存,如果有就返回,没有就加载
  cache.get(classLoader);
  if (result != null) {
   return result;
  }
  try {
      //通过类加载器加载所有jar包中包含META-INFO/spring.factorys的文件资源路径
   Enumeration urls = (classLoader != null ?
     classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
     ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
   result = new LinkedMultiValueMap<>();
   while (urls.hasMoreElements()) {
    URL url = urls.nextElement();
    UrlResource resource = new UrlResource(url);
    //实例化properties对象,并加载路径中的spring.factorys文件内容
    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
    for (Map.Entry, ?> entry : properties.entrySet()) {
     String factoryClassName = ((String)
     //获取key值
     entry.getKey()).trim();
     //对value值进行都好拆分处理
     for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
        //将key和value值存入result中 result.add(factoryClassName, factoryName.trim());
     }
    }
   }
   //将结果存入缓存
   cache.put(classLoader, result);
   return result;
  }
  catch (IOException ex) {
   throw new IllegalArgumentException("Unable to load factories from location [" +
     FACTORIES_RESOURCE_LOCATION + "]", ex);
  }
 }    感谢你能够认真阅读完这篇文章,希望小编分享的“springboot中getSpringFactoriesInstances源码的示例分析”这篇文章对大家有帮助,同时也希望大家多多支持创新互联,关注创新互联行业资讯频道,更多相关知识等着你来学习!
本文标题:springboot中getSpringFactoriesInstances源码的示例分析
文章URL:http://www.cqwzjz.cn/article/ipgsdh.html

 建站
建站
 咨询
咨询 售后
售后
 建站咨询
建站咨询 
 