SpringBoot源码解读四【spring.factories机制】

SPI机制

SPI的全名为Service Provider Interface 简单来讲,系统里抽象的各种模块,可以有很多不同的实现方案,比如xml解析模块、加密模块等。面向对象编程,模块之间基于接口编程,模块之间不对实现类进行硬编码。为了实现模块装配的时候不再程序里动态指明。一旦代码里涉及具体的实现类,就违反了可插拔的原则,这就需要一种服务发现机制。
Java SPI:为某个接口寻找服务实现的机制。

spring.factories机制

Spring Boot也存在与SPI类似的的加载机制,它在META-INF/spring.factories文件中配置接口的实现类名称,然后程序读取这些配置文件并实例化。这也是Spring boot starter实现的基础

源码

在SpringApplication的构造函数中,存在如下方法getSpringFactoriesInstances

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
	this.resourceLoader = resourceLoader;
	Assert.notNull(primarySources, "PrimarySources must not be null");
	this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
	this.webApplicationType = WebApplicationType.deduceFromClasspath();
	this.bootstrapRegistryInitializers = new ArrayList<>(
			getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
	setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	this.mainApplicationClass = deduceMainApplicationClass();
}

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
	return getSpringFactoriesInstances(type, new Class<?>[] {});
}

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
	ClassLoader classLoader = getClassLoader();
	// 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;
}

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;
}

SpringFactoriesLoader

  • loadFactories 根据接口类获取实现类实例,返回实现类的实例集合
  • loadFactoryNames 根据接口类获取实现类名称,返回实现类名集合
public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
	Assert.notNull(factoryType, "'factoryType' must not be null");
	ClassLoader classLoaderToUse = classLoader;
	if (classLoaderToUse == null) {
		classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
	}
	// 根据factory类型 获取对应的名字
	List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse);
	if (logger.isTraceEnabled()) {
		logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames);
	}
	List<T> result = new ArrayList<>(factoryImplementationNames.size());
	for (String factoryImplementationName : factoryImplementationNames) {
		result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
	}
	//基于注解排序
	AnnotationAwareOrderComparator.sort(result);
	return result;
}

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
	ClassLoader classLoaderToUse = classLoader;
	if (classLoaderToUse == null) {
		classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
	}
	String factoryTypeName = factoryType.getName();
	return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}

// 加载META-INF/spring.factories属性资源
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
	Map<String, List<String>> result = cache.get(classLoader);
	if (result != null) {
		return result;
	}

	result = new HashMap<>();
	try {
		// 获取spring.factories资源
		Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
		while (urls.hasMoreElements()) {
			URL url = urls.nextElement();
			UrlResource resource = new UrlResource(url);
			Properties properties = PropertiesLoaderUtils.loadProperties(resource);
			for (Map.Entry<?, ?> entry : properties.entrySet()) {
				String factoryTypeName = ((String) entry.getKey()).trim();
				String[] factoryImplementationNames =
						StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
				for (String factoryImplementationName : factoryImplementationNames) {
					result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
							.add(factoryImplementationName.trim());
				}
			}
		}

		// Replace all lists with unmodifiable lists containing unique elements
		result.replaceAll((factoryType, implementations) -> implementations.stream().distinct()
				.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
		cache.put(classLoader, result);
	}
	catch (IOException ex) {
		throw new IllegalArgumentException("Unable to load factories from location [" +
				FACTORIES_RESOURCE_LOCATION + "]", ex);
	}
	return result;
}


// 实例化
private static <T> T instantiateFactory(String factoryImplementationName, Class<T> factoryType, ClassLoader classLoader) {
	try {
		Class<?> factoryImplementationClass = ClassUtils.forName(factoryImplementationName, classLoader);
		if (!factoryType.isAssignableFrom(factoryImplementationClass)) {
			throw new IllegalArgumentException(
					"Class [" + factoryImplementationName + "] is not assignable to factory type [" + factoryType.getName() + "]");
		}
		return (T) ReflectionUtils.accessibleConstructor(factoryImplementationClass).newInstance();
	}
	catch (Throwable ex) {
		throw new IllegalArgumentException(
			"Unable to instantiate factory class [" + factoryImplementationName + "] for factory type [" + factoryType.getName() + "]",
			ex);
	}
}

流程

  1. 通过classLoader加载META-INF/spring.factories资源
  2. spring.factories转换为key-value的属性对象,放到缓存对象中Map<ClassLoader, Map<String, List>>
  3. 根据classloader+Key(factoryType),根据返回对应的类名集合
  4. 根据类名通过反射实现类的实例化对象
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值