spring boot 源码分析(二) 配置文件加载

一、前言

上篇讲到了spring boot 通过SpringFactoriesLoader.loadFactoryNames进行加载工厂实例名称列表。本篇是接着上篇继续从源码讲解spring boot加载配置文件的流程,

二、代码解读

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
			Class<?>[] parameterTypes, Object... args) {
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		// Use names and ensure unique to protect against duplicates
		Set<String> names = new LinkedHashSet<>(
				SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
				classLoader, args, names);
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

既然他加载完工厂实例名称列表了,那么他如何初始化呢。我们继续往下看,他有个

createSpringFactoriesInstances()

//用来创建spring工厂实例
private <T> List<T> createSpringFactoriesInstances(Class<T> type,
			Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args,
			Set<String> names) {
		List<T> instances = new ArrayList<>(names.size());//创建实例list,用来装创建好的实例
		for (String name : names) {
			try {
				Class<?> instanceClass = ClassUtils.forName(name, classLoader);//创建没有被链接的类,此处底层用到了 ClassLoader.loadClass 关于它和 Class.forName的区别 可以参考https://www.cnblogs.com/suibianle/p/6676215.html
				Assert.isAssignable(type, instanceClass);//判断instanceClass是否是type类型
				Constructor<?> constructor = instanceClass
						.getDeclaredConstructor(parameterTypes);//获取instanceClass构造
				T instance = (T) BeanUtils.instantiateClass(constructor, args);//实例化
				instances.add(instance);
			}
			catch (Throwable ex) {
				throw new IllegalArgumentException(
						"Cannot instantiate " + type + " : " + name, ex);
			}
		}
		return instances;
	}

经过此方法后,关于type类型的工厂实例就初始化完成了。

猜你喜欢

转载自my.oschina.net/u/1178126/blog/1820854