SpringBoot 基础概念:SpringApplication#getSpringFactoriesInstances
- SpringApplication#getSpringFactoriesInstances
SpringApplication#getSpringFactoriesInstances
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = getClassLoader();// Use names and ensure unique to protect against duplicatesSet<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances;
}private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,ClassLoader classLoader, Object[] args, Set<String> names) {List<T> 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;
}
-
从方法名称就能知道,这个方法是得到spring.factories文件的实例化对象
-
参数:type的类名为key,也就是上图黄色的部分,真正实例化的类是上图中绿色的部分。parameterTypes为构造器的参数类型。args为构造方法中参数的值。
-
获取到ClassLoader,通过ClassLoader加载到所有的META-INF/spring.factories文件资源。Properties#load拿到key value信息,type为key(途中黄色部分),value逗号分隔返回Set去重后的类名。通过反射创建实例。
-
在解析spring.factories文件的过程中,第一次就将所有的spring.factories文件加载了,对classLoader进行了缓存,避免重复加载创建多个实例。
-
在SpringBoot启动的过程中,spring.factories资源在一开始就被解析了。