spring boot AutoConfiguration.replacements 文件的作用

spring boot AutoConfiguration.replacements 文件的作用

自动配置类可能会在 @AutoConfigureBefore@AutoConfigureAfter 排序注解中被引用,也可能在 @SpringBootApplication(exclude =, excludeName = )@EnableAutoConfiguration(exclude = , excludeName = )spring.autoconfigure.exclude 属性值中被引用用于排除某些自动配置。

如果我们想要重命名自动配置类,或者将其移动到其他的包中,就会导致自动配置排序和排除失效。spring boot 提供了 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.replacements 文件用于解决这个问题,在文件中写入旧类和新类的映射关系之后,spring boot 会先将注解和属性中的旧类名替换为新类名,再处理自动配置类的排序、排除。

例如:

旧类=新类

properties 复制代码
com.mycorp.libx.autoconfigure.LibXAutoConfiguration=com.mycorp.libx.autoconfigure.core.LibXAutoConfiguration

文件的读取由 AutoConfigurationReplacementsload 方法实现:

java 复制代码
package org.springframework.boot.autoconfigure;

final class AutoConfigurationReplacements {

	private static final String LOCATION = "META-INF/spring/%s.replacements";

	private final Map<String, String> replacements;

	private AutoConfigurationReplacements(Map<String, String> replacements) {
		this.replacements = Map.copyOf(replacements);
	}

	Set<String> replaceAll(Set<String> classNames) {
		Set<String> replaced = new LinkedHashSet<>(classNames.size());
		for (String className : classNames) {
			replaced.add(replace(className));
		}
		return replaced;
	}

	String replace(String className) {
		return this.replacements.getOrDefault(className, className);
	}

	static AutoConfigurationReplacements load(Class<?> annotation, @Nullable ClassLoader classLoader) {
		Assert.notNull(annotation, "'annotation' must not be null");
		ClassLoader classLoaderToUse = decideClassloader(classLoader);
        // META-INF/spring/%s.replacements
        // annotation 是 AutoConfiguration,全限定名是 org.springframework.boot.autoconfigure.AutoConfiguration
        // 格式化之后就是 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.replacements
		String location = String.format(LOCATION, annotation.getName());
        // 获取多个 jar 中的文件路径
		Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
		Map<String, String> replacements = new HashMap<>();
        // 循环读取 AutoConfiguration.replacements 文件
		while (urls.hasMoreElements()) {
			URL url = urls.nextElement();
            // readReplacements 使用 Properties.load 加载文件
			replacements.putAll(readReplacements(url));
		}
		return new AutoConfigurationReplacements(replacements);
	}

	private static ClassLoader decideClassloader(@Nullable ClassLoader classLoader) {
		if (classLoader == null) {
			return ImportCandidates.class.getClassLoader();
		}
		return classLoader;
	}

	private static Enumeration<URL> findUrlsInClasspath(ClassLoader classLoader, String location) {
		try {
			return classLoader.getResources(location);
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Failed to load configurations from location [" + location + "]", ex);
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private static Map<String, String> readReplacements(URL url) {
		try (BufferedReader reader = new BufferedReader(
				new InputStreamReader(new UrlResource(url).getInputStream(), StandardCharsets.UTF_8))) {
			Properties properties = new Properties();
            // 加载 .replacements 文件
			properties.load(reader);
			return (Map) properties;
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load replacements from location [" + url + "]", ex);
		}
	}
}

参考

Creating Your Own Auto-configuration :: Deprecating and Replacing Auto-configuration Classes

相关推荐
Patrick在香港2 小时前
Python Docker镜像从1.2GB到89MB:多阶段构建的完整优化实录
java·python·docker·信息可视化·容器·数据分析·ai编程
上海安当技术2 小时前
敏感数据怎么防拖库?信封加密(DEK+KEK 二层密钥)架构设计与 Java 实战
java·开发语言·python
我是唐青枫2 小时前
Java JCommander 实战详解:用注解解析命令行参数
java·开发语言
大鹏说大话2 小时前
C++ 内存布局详解:类、虚函数、虚表底层原理
java·开发语言
还是鼠鼠3 小时前
Spring AI连接DeepSeek与通义千问:application.yaml配置详解
java·通义千问·spring ai·deepseek
计算机小白一个4 小时前
蓝桥杯 Java B 组之哈希表应用(两数之和、重复元素判断)
java·数据结构·算法·蓝桥杯
sunburn-5 小时前
Java 队列全面详解:从入门到面试实战
java·开发语言·汇编·ide·idea
vx-程序开发5 小时前
springboot农产品运输服务平台---附源码75498
java·javascript·spring boot·python·eclipse·django·php
攻城有术5 小时前
专项攻克——spring、springMVC、springBoot、springCloud的启动流程
spring boot·spring·spring cloud
独行侠影a6 小时前
SpringBoot 分布式锁实战:Redisson 解决订单超卖并发问题
spring boot·分布式·后端