/** * 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: * * SpringFactoriesLoader#loadFactories设计用于加载和实例化指定类型的工厂,这些工厂类型的定义 * 来自classpath中多个JAR包内常量FACTORIES_RESOURCE_LOCATION所指定的那些spring.factories文件。 * spring.factories文件的格式必须是{@link Properties}格式,每条属性的key必须是接口或者抽象类的全限定名, * 而属性值value是一个逗号分割的实现类的名称。 * * <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. * * @author Arjen Poutsma * @author Juergen Hoeller * @author Sam Brannen * @since 3.2 */ publicfinalclassSpringFactoriesLoader {
/** * The location to look for factories. * <p>Can be present in multiple JAR files. * * 在classpath中的多个JAR中要扫描的工厂配置文件的在本JAR包中的路径。 * 实际上,Springboot的每个 autoconfigure包都包含一个这样的文件。 */ publicstaticfinalStringFACTORIES_RESOURCE_LOCATION="META-INF/spring.factories";
/** * 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. * <p>As of Spring Framework 5.3, if duplicate implementation class names are * discovered for a given factory type, only one instance of the duplicated * implementation type will be instantiated. * @param factoryType 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> factoryType, @Nullable ClassLoader classLoader) { Assert.notNull(factoryType, "'factoryType' must not be null"); ClassLoaderclassLoaderToUse= classLoader; if (classLoaderToUse == null) { classLoaderToUse = SpringFactoriesLoader.class.getClassLoader(); } // 加载类型为factoryClass的工厂的名称,其实是一个个的全限定类名,使用指定的classloader: List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse); if (logger.isTraceEnabled()) { logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames); } List<T> result = newArrayList<>(factoryImplementationNames.size()); // 实例化所加载的每个工厂类 for (String factoryImplementationName : factoryImplementationNames) { result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse)); } // 排序 AnnotationAwareOrderComparator.sort(result); return result; }
/** * Load the fully qualified class names of factory implementations of the * given type from {@value #FACTORIES_RESOURCE_LOCATION}, using the given * class loader. * <p>As of Spring Framework 5.3, if a particular implementation class name * is discovered more than once for the given factory type, duplicates will * be ignored. * @param factoryType 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<?> factoryType, @Nullable ClassLoader classLoader) { ClassLoaderclassLoaderToUse= classLoader; if (classLoaderToUse == null) { classLoaderToUse = SpringFactoriesLoader.class.getClassLoader(); } StringfactoryTypeName= factoryType.getName(); // 1. 使用指定的classloader扫描classpath上所有的JAR包中的文件META-INF/spring.factories,加载其中的多值 // 工厂属性定义,使用多值Map的形式返回, // 2. 返回多值Map中key为factoryClassName的工厂名称列表,如果没有相应的entry,返回空列表而不是返回null return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList()); }
如果您已经创建了自动配置,那么应该将注册从META-INF/spring.factories转移到一个名为META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports的新文件。每一行都包含自动配置的完全限定名。请参考: the included auto-configurations