/** * General purpose factory loading mechanism for internal use within the framework. * * <p>{@code SpringFactoriesLoader} {@linkplain #loadFactories loads} and instantiates * factories of a given type from {@value #FACTORIES_RESOURCE_LOCATION} files which * may be present in multiple JAR files in the classpath. The {@code spring.factories} * file must be in {@link Properties} format, where the key is the fully qualified * name of the interface or abstract class, and the value is a comma-separated list of * implementation class names. For example: * * <pre class="code">example.MyService=example.MyServiceImpl1,example.MyServiceImpl2</pre> * * where {@code example.MyService} is the name of the interface, and {@code MyServiceImpl1} * and {@code MyServiceImpl2} are two implementations. */
从包名我们就可以看出,SpringFactoriesLoader 是 Spring Framework 就已经提供的工具类,😈 而不是 Spring Boot 所特有的。
2.1 构造方法
// SpringFactoriesLoader.java
/** * The location to look for factories. * <p>Can be present in multiple JAR files. */ publicstaticfinal String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
/** * Load the fully qualified class names of factory implementations of the * given type from {@value #FACTORIES_RESOURCE_LOCATION}, using the given * class loader. * @param factoryClass the interface or abstract class representing the factory * @param classLoader the ClassLoader to use for loading resources; can be * {@code null} to use the default * @throws IllegalArgumentException if an error occurs while loading factory names * @see #loadFactories */ publicstatic List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader){ // 获得接口的类名 String factoryClassName = factoryClass.getName(); // 加载 FACTORIES_RESOURCE_LOCATION 配置文件,获得接口对应的实现类名们 return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList()); }
/** * Load and instantiate the factory implementations of the given type from * {@value #FACTORIES_RESOURCE_LOCATION}, using the given class loader. * <p>The returned factories are sorted through {@link AnnotationAwareOrderComparator}. * <p>If a custom instantiation strategy is required, use {@link #loadFactoryNames} * to obtain all registered factory names. * @param factoryClass the interface or abstract class representing the factory * @param classLoader the ClassLoader to use for loading (can be {@code null} to use the default) * @throws IllegalArgumentException if any factory implementation class cannot * be loaded or if an error occurs while instantiating any factory * @see #loadFactoryNames */ publicstatic <T> List<T> loadFactories(Class<T> factoryClass, @Nullable ClassLoader classLoader){ Assert.notNull(factoryClass, "'factoryClass' must not be null"); // 获得 ClassLoader ClassLoader classLoaderToUse = classLoader; if (classLoaderToUse == null) { classLoaderToUse = SpringFactoriesLoader.class.getClassLoader(); } // 获得接口对应的实现类名们 List<String> factoryNames = loadFactoryNames(factoryClass, classLoaderToUse); if (logger.isTraceEnabled()) { logger.trace("Loaded [" + factoryClass.getName() + "] names: " + factoryNames); } // 遍历 factoryNames 数组,创建实现类的对象 List<T> result = new ArrayList<>(factoryNames.size()); for (String factoryName : factoryNames) { result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse)); } // 排序 AnnotationAwareOrderComparator.sort(result); return result; }
privatestatic <T> T instantiateFactory(String instanceClassName, Class<T> factoryClass, ClassLoader classLoader){ try { // 获得 Class 类 Class<?> instanceClass = ClassUtils.forName(instanceClassName, classLoader); // 判断是否实现了指定接口 if (!factoryClass.isAssignableFrom(instanceClass)) { thrownew IllegalArgumentException("Class [" + instanceClassName + "] is not assignable to [" + factoryClass.getName() + "]"); } // 创建对象 return (T) ReflectionUtils.accessibleConstructor(instanceClass).newInstance(); } catch (Throwable ex) { thrownew IllegalArgumentException("Unable to instantiate factory class: " + factoryClass.getName(), ex); } }