// SpringFactoriesLoader.java
/**
* 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.
*/
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);
/**
* 缓存
*
* KEY1 :ClassLoader
* KEY2 :接口的类名
* VALUE :实现的类名的数组。注意哟,是个 MultiValueMap 类
*/
private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap<>();
private SpringFactoriesLoader() {
}
FACTORIES_RESOURCE_LOCATION 静态属性,定义了读取的是 "META-INF/spring.factories" 配置文件。并且,每个 JAR 文件里,都可以有一个这个配置文件。
// SpringFactoriesLoader.java
/**
* 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
*/
public static <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;
}
private static <T> T instantiateFactory(String instanceClassName, Class<T> factoryClass, ClassLoader classLoader) {
try {
// 获得 Class 类
Class<?> instanceClass = ClassUtils.forName(instanceClassName, classLoader);
// 判断是否实现了指定接口
if (!factoryClass.isAssignableFrom(instanceClass)) {
throw new IllegalArgumentException("Class [" + instanceClassName + "] is not assignable to [" + factoryClass.getName() + "]");
}
// 创建对象
return (T) ReflectionUtils.accessibleConstructor(instanceClass).newInstance();
} catch (Throwable ex) {
throw new IllegalArgumentException("Unable to instantiate factory class: " + factoryClass.getName(), ex);
}
}