SpringFactoriesLoader

  • Author: HuiFer
  • 源码阅读仓库: SourceHot-spring-boot

  • 全路径 : org.springframework.core.io.support.SpringFactoriesLoader

  • 测试类 : org.springframework.core.io.support.SpringFactoriesLoaderTests

loadFactories

  • 加载并实例化工厂
  1. public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
  2. Assert.notNull(factoryType, "'factoryType' must not be null");
  3. ClassLoader classLoaderToUse = classLoader;
  4. if (classLoaderToUse == null) {
  5. classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
  6. }
  7. // 工厂实现类名称
  8. List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse);
  9. if (logger.isTraceEnabled()) {
  10. logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames);
  11. }
  12. List<T> result = new ArrayList<>(factoryImplementationNames.size());
  13. for (String factoryImplementationName : factoryImplementationNames) {
  14. // 将实例化的工厂放入结果集合
  15. result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
  16. }
  17. // 排序
  18. AnnotationAwareOrderComparator.sort(result);
  19. return result;
  20. }

loadSpringFactories

  • 获取接口的实现类名
  1. private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
  2. MultiValueMap<String, String> result = cache.get(classLoader);
  3. if (result != null) {
  4. return result;
  5. }
  6. try {
  7. // 找 META-INF/spring.factories
  8. Enumeration<URL> urls = (classLoader != null ?
  9. classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
  10. ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
  11. result = new LinkedMultiValueMap<>();
  12. while (urls.hasMoreElements()) {
  13. // 获取 路由地址
  14. URL url = urls.nextElement();
  15. // url 解析
  16. UrlResource resource = new UrlResource(url);
  17. // Properties 解析
  18. Properties properties = PropertiesLoaderUtils.loadProperties(resource);
  19. // 循环解析结果
  20. for (Map.Entry<?, ?> entry : properties.entrySet()) {
  21. String factoryTypeName = ((String) entry.getKey()).trim();
  22. for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
  23. // 放入list
  24. result.add(factoryTypeName, factoryImplementationName.trim());
  25. }
  26. }
  27. }
  28. // 放入缓存
  29. cache.put(classLoader, result);
  30. return result;
  31. }
  32. catch (IOException ex) {
  33. throw new IllegalArgumentException("Unable to load factories from location [" +
  34. FACTORIES_RESOURCE_LOCATION + "]", ex);
  35. }
  36. }
  • 存放在 测试目录下的META-INF/spring.factories

    1. org.springframework.core.io.support.DummyFactory =\
    2. org.springframework.core.io.support.MyDummyFactory2, \
    3. org.springframework.core.io.support.MyDummyFactory1
    4. java.lang.String=\
    5. org.springframework.core.io.support.MyDummyFactory1
    6. org.springframework.core.io.support.DummyPackagePrivateFactory=\
    7. org.springframework.core.io.support.DummyPackagePrivateFactory
  • Enumeration<URL> urls 变量存放的是 扫描到的META-INF/spring.factories 路径

  • while 代码简单描述

    1. 获取文件路径
    2. 文件路径解析
    3. 读取文件 Properties 解析
    4. 放入返回结果
    5. 放入缓存

instantiateFactory

  1. @SuppressWarnings("unchecked")
  2. private static <T> T instantiateFactory(String factoryImplementationName, Class<T> factoryType, ClassLoader classLoader) {
  3. try {
  4. Class<?> factoryImplementationClass = ClassUtils.forName(factoryImplementationName, classLoader);
  5. if (!factoryType.isAssignableFrom(factoryImplementationClass)) {
  6. throw new IllegalArgumentException(
  7. "Class [" + factoryImplementationName + "] is not assignable to factory type [" + factoryType.getName() + "]");
  8. }
  9. return (T) ReflectionUtils.accessibleConstructor(factoryImplementationClass).newInstance();
  10. }
  11. catch (Throwable ex) {
  12. throw new IllegalArgumentException(
  13. "Unable to instantiate factory class [" + factoryImplementationName + "] for factory type [" + factoryType.getName() + "]",
  14. ex
  15. );
  16. }
  17. }
  • 反射创建