Home > Java > javaTutorial > body text

SpringBoot spring.factories loading timing source code analysis

WBOY
Release: 2023-05-17 21:31:04
forward
1352 people have browsed it

The role of spring.factories

This is similar to the SPI function in Java. When SpringBoot starts, it will read the META-INF/spring.factories files under all jar packages;

And map the implementation classes corresponding to the interfaces/abstract classes in the file, and instantiate the corresponding implementation classes when needed

Let’s analyze the source code and take a lookspring.factoriesUsage scenarios

Source code analysis

Start SpringApplication and look at the construction method

	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();
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}
Copy after login

The method getSpringFactoriesInstances(ApplicationContextInitializer.class) is used to obtain the specified class instance in Spring; and when obtaining it, the corresponding instance class is instantiated based on the content in the file path META-INF/spring.factories read in the entire project. ;

For example, the ApplicationContextInitializer here is an interface, so which of its implementation classes should be instantiated? Then look for the META-INF/spring.factories file; then we found this file in the spring-boot:2.1.0jar package

SpringBoot spring.factories loading timing source code analysis

Read that the implementation class that needs to be instantiated is

org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
Copy after login

and also found this file in spring-boot-autoconfigure-2.1.0.RELEASE.jar

SpringBoot spring.factories loading timing source code analysis

Then the two implementation classes in the file will also be instantiated; plus the above 4, there are 6 in total

org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
Copy after login

SpringBoot spring.factories loading timing source code analysis

You can see that not only the instance classes of org.springframework.context.ApplicationContextInitializer are parsed; but all of them are parsed and saved. Other classes will need it next time When instantiated, it can be taken directly from the memory;

After the above process obtains the instance class, the next step is the instantiation process

	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;
	}
Copy after login

MethodcreateSpringFactoriesInstancesIt is the process of creating an instance; you can see that the corresponding interface class is passed inorg.springframework.context.ApplicationContextInitializer ;Then the corresponding implementation class will be instantiated;

	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;
	}
Copy after login

If there is nothing special to explain about the instantiation process;

There is a method above AnnotationAwareOrderComparator.sort(instances);is used to sort all instances; the implementation class needs to implement Interface Ordered; The smaller the value returned by getOrder, the higher the priority

Usage

After knowing the usage of spring.factories, then we You can use this feature to achieve your own purposes;

For example, we can also write an implementation class of the interface classApplicationContextInitializer.

The above is the detailed content of SpringBoot spring.factories loading timing source code analysis. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:yisu.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template