Home / Class/ AutoConfigurationReplacements Class — spring-boot Architecture

AutoConfigurationReplacements Class — spring-boot Architecture

Architecture documentation for the AutoConfigurationReplacements class in AutoConfigurationReplacements.java from the spring-boot codebase.

Entity Profile

Relationship Graph

Source Code

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationReplacements.java lines 45–135

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

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null || getClass() != obj.getClass()) {
			return false;
		}
		return this.replacements.equals(((AutoConfigurationReplacements) obj).replacements);
	}

	@Override
	public int hashCode() {
		return this.replacements.hashCode();
	}

	/**
	 * Loads the relocations from the classpath. Relocations are stored in files named
	 * {@code META-INF/spring/full-qualified-annotation-name.replacements} on the
	 * classpath. The file is loaded using {@link Properties#load(java.io.InputStream)}
	 * with each entry containing an auto-configuration class name as the key and the
	 * replacement class name as the value.
	 * @param annotation annotation to load
	 * @param classLoader class loader to use for loading
	 * @return list of names of annotated classes
	 */
	static AutoConfigurationReplacements load(Class<?> annotation, @Nullable ClassLoader classLoader) {
		Assert.notNull(annotation, "'annotation' must not be null");
		ClassLoader classLoaderToUse = decideClassloader(classLoader);
		String location = String.format(LOCATION, annotation.getName());
		Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
		Map<String, String> replacements = new HashMap<>();
		while (urls.hasMoreElements()) {
			URL url = urls.nextElement();
			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();
			properties.load(reader);
			return (Map) properties;
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load replacements from location [" + url + "]", ex);
		}
	}

}

Domain

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free