源码分析之Spring Boot如何利用Spring Factories机制进行自动注入

本文详细解析了Spring Boot如何利用Spring Factories进行自动注入,包括SpringFactoriesLoader的作用、spring.factories文件的位置和内容,以及如何在项目中自定义配置。通过示例展示了spring-boot-starter的实现,阐述了Spring Boot启动时AutoConfigurationImportSelector的工作原理,揭示了Spring Factories作为扩展点的重要角色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

本文所涉及spring/spring boot代码,请参考spring boot 2.2.6对应版本。

我们在刚学习spring boot时,有没有一个困惑:spring boot能够自动实例化很多第三方的依赖库?比如eureka、druid等。这个就涉及到spring boot的扩展机制spring factories。

简单来讲,spring factories类似与Java SPI机制,利用该机制,我们能够自定义实现一些SDK或是spring boot starter,其实例化过程由我们来实现,使用方只需要在项目中引入包、不需要或是只需做很少的配置。

Spring Factories的核心

spring factories机制核心在spring-core包中定义的SpringFactoriesLoader类,该类的公有方法只有2个:

/*
根据接口类获取其实现类的实例,这个方法返回的是对象列表。
Load and instantiate the factory implementations of the given type from "META-INF/spring.factories", using the given class loader.
The returned factories are sorted through AnnotationAwareOrderComparator.
If a custom instantiation strategy is required, use loadFactoryNames(java.lang.Class<?>, java.lang.ClassLoader) to obtain all registered factory names.
*/
public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader)
    
/*
根据接口获取其接口类的名称,这个方法返回的是类名的列表。
Load the fully qualified class names of factory implementations of the given type from "META-INF/spring.factories", using the given class loader.
*/
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader)

而上面这两个方法,最终都会调用一个SpringFactoriesLoader的私有方法loadSpringFactories,从指定的ClassLoader中获取spring.factories文件,并解析得到类名列表。具体代码如下:

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
   
   
		MultiValueMap<String, String> result = cache.get(classLoader);
		if (result != null) {
   
   
			return result;
		}

		try {
   
   
			Enumeration<URL> urls = (classLoader != null ?
					classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
					ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
			result = new LinkedMultiValueMap<>();
			while (urls.hasMoreElements()) {
   
   
				URL url = urls.nextElement();
				UrlResource resource = new UrlResource(url);
				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
				for (Map.Entry<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值