spring-boot解析spring.factories文件
启动SpringBoot自动装配的工厂类方法实现
/**
* 解析 spring.factories 文件
*
* @return 读取到的所有数据
*/
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader){
try {
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources("META-INF/spring.factories") :
ClassLoader.getSystemResources("META-INF/spring.factories"));
MultiValueMap<String, String> result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryClassName = ((String) entry.getKey()).trim();
for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryClassName, factoryName.trim());
}
}
}
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", ex);
}
}
/**
* 反射实例化
*/
private static <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;
}
public static void main(String[] args) throws IOException {
ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
// 解析 spring.factories 文件
Map<String, List<String>> maps = loadSpringFactories(classLoader);
// 获取指定的类 ApplicationContextInitializer 配置
String className = ApplicationContextInitializer.class.getName();
List<String> values = maps.getOrDefault(className,Collections.emptyList());
// 反射实例化类
Set<String> names = new LinkedHashSet<>(values);
List<ApplicationContextInitializer> instances = createSpringFactoriesInstances(ApplicationContextInitializer.class, new Class<?>[]{}, classLoader, args, names);
for (ApplicationContextInitializer instance : instances) {
System.out.println(instance.toString());
}
}