Spring原始碼之事務(一)— TransactionAutoConfiguration自動配置

曹自標發表於2020-11-19

總結:

  • 在ConfigurationClassParser#parse()中會對deferredImportSelectorHandler進行處理(在處理@ComponentScan 自己所寫@Component的類後)
  • 處理過程中會呼叫SpringFactoriesLoader#loadFactoryNames(),去查詢所有jar下面META-INF/spring.factories中key為org.springframework.boot.autoconfigure.EnableAutoConfiguration的值
  • ConfigurationClassPostProcessor#processConfigBeanDefinitions()中loadBeanDefinitions對TransactionAutoConfiguration進行BeanDefinition的載入,並註冊IOC容器

TransactionAutoConfiguration的BeanDefinition載入解析

呼叫鏈:

AbstractApplicationContext#refresh() --> AbstractApplicationContext#invokeBeanFactoryPostProcessors() --> PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors() --> PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors() --> ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry()--> ConfigurationClassPostProcessor#processConfigBeanDefinitions() --> ConfigurationClassPostProcessor#parse() --> ConfigurationClassParser#process() --> ConfigurationClassParser$DeferredImportSelectorGroupingHandler#processGroupImports() --> ConfigurationClassParser#processImports() --> ConfigurationClassParser#processConfigurationClass() --> ConfigurationClassParser#doProcessConfigurationClass()

ConfigurationClassParser#parse() 對延遲ImportSelector進行處理

private final DeferredImportSelectorHandler deferredImportSelectorHandler = new DeferredImportSelectorHandler();

public void parse(Set<BeanDefinitionHolder> configCandidates) {
	this.deferredImportSelectorHandler.process();
}

呼叫DeferredImportSelectorGroupingHandler#processGroupImports()

public void process() {
	List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
	this.deferredImportSelectors = null;
	try {
		if (deferredImports != null) {
			DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
			deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
			// 給ConfigurationClassParser.groupings賦值
			deferredImports.forEach(handler::register);
			// DeferredImportSelectorGroupingHandler處理
			handler.processGroupImports();
		}
	}
	finally {
		this.deferredImportSelectors = new ArrayList<>();
	}

主要handler.processGroupImports()中 grouping.getImports()會查詢出所有ConfigurationClassParser$DeferredImportSelectorGroupingHandler中的imports

public void processGroupImports() {
	for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
		
		grouping.getImports().forEach(entry -> {
			ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
			try {
				processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
						Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
						exclusionFilter, false);
			}
		}
	}
}

ConfigurationClassParser$DeferredImportSelectorGroupingHandler#getImports()

public Iterable<Group.Entry> getImports() {
	for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
		this.group.process(deferredImport.getConfigurationClass().getMetadata(),
				deferredImport.getImportSelector());
	}
	return this.group.selectImports();
}

會呼叫AutoConfigurationImportSelector#process()

public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
	AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
			.getAutoConfigurationEntry(annotationMetadata);
	this.autoConfigurationEntries.add(autoConfigurationEntry);
	for (String importClassName : autoConfigurationEntry.getConfigurations()) {
		this.entries.putIfAbsent(importClassName, annotationMetadata);
	}
}

會呼叫AutoConfigurationImportSelector#getAutoConfigurationEntry()

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
	List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
	......
	return new AutoConfigurationEntry(configurations, exclusions);
}

其中AutoConfigurationImportSelector#getCandidateConfigurations()會查詢所有jar下面META-INF/spring.factories,進行loadFactoryNames。

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
	List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
			getBeanClassLoader());
	return configurations;
}

SpringFactoriesLoader#loadFactoryNames()

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

SpringFactoriesLoader#loadSpringFactories()

private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {

	result = new HashMap<>();
	try {
		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());
				}
			}
		}
	}
	
	return result;
}

其中spring-boot-autoconfigure-XX.jar下面META-INF/spring.factories檔案中就有:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration

附:其中ConfigurationClassParser.groupings賦值,是在ConfigurationClassParser#register()執行的

public void register(DeferredImportSelectorHolder deferredImport) {
	Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
	DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
			(group != null ? group : deferredImport),
			key -> new DeferredImportSelectorGrouping(createGroup(group)));
	grouping.add(deferredImport);
	this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
			deferredImport.getConfigurationClass());
}

loadBeanDefinitions

this.reader.loadBeanDefinitions(configClasses)進行BeanDefinition的載入,並註冊到IOC容器

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    this.reader.loadBeanDefinitions(configClasses);
}

相關文章