Spring boot源码初识二 自动配置原理

自动配置源码流程图

在这里插入图片描述

自动配置源码解析

@SpringBootApplication

spring boot提供的注解,标明是spring boot项目,进入此注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
//开启自动配置类注解 ***重点***
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

	//排除指定自动注入配置类
	@AliasFor(annotation = EnableAutoConfiguration.class)
	Class<?>[] exclude() default {};
	
	//排除指定自动注入配置类名
	@AliasFor(annotation = EnableAutoConfiguration.class)
	String[] excludeName() default {};

	//ComponentScan的别名,可以设置扫描包路径
	@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
	String[] scanBasePackages() default {};
	
	//扫描指定类
	@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
	Class<?>[] scanBasePackageClasses() default {};
	...
}

@EnableAutoConfiguration

开启自动配置,自动扫描项目中所有jar包中的META-INF/spring.factories文件中的EnableAutoConfiguration对应的类名,将这些类当成配置类载入spring容器

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
//关键类,通过此类实现自动导入配置
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	Class<?>[] exclude() default {};

	String[] excludeName() default {};

}

@Import(AutoConfigurationImportSelector.class)

实现DeferredImportSelector接口,此接口spring会延迟加载,在所有配置都加载完才会加载此类
当前类的Ordered 设置为Ordered.LOWEST_PRECEDENCE - 1,表示如果存在其他DeferredImportSelector,当前类的优先级比最低优先级高一级

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
		ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
	...
	/***
	* 通常ImportSelector都是重写selectImports来告诉spring导入类都有哪些
	**但是当前类,通过重写getImportGroup,返回AutoConfigurationGroup,spring会调用此类的process方法获取导入类
	**/
	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}
	...
	/***
	* 通知spring通过AutoConfigurationGroup类载入配置类
	*/
	@Override
	public Class<? extends Group> getImportGroup() {
		return AutoConfigurationGroup.class;
	}

}

AutoConfigurationGroup.process

获取配置和返回给spring需要导入的类

private static class AutoConfigurationGroup
			implements DeferredImportSelector.Group, BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware {
	...
	/***
	* 调用getAutoConfigurationEntry方法获取需要自动注入的配置类
	*/	
	@Override
	public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
		Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
				() -> String.format("Only %s implementations are supported, got %s",
AutoConfigurationImportSelector.class.getSimpleName(),
						deferredImportSelector.getClass().getName()));
		AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
				.getAutoConfigurationEntry(annotationMetadata);
		this.autoConfigurationEntries.add(autoConfigurationEntry);
		for (String importClassName : autoConfigurationEntry.getConfigurations()) {
			this.entries.putIfAbsent(importClassName, annotationMetadata);
		}
	}
	...
	/***
	* 此类返回注入的配置类
	*/
	@Override
	public Iterable<Entry> selectImports() {
		if (this.autoConfigurationEntries.isEmpty()) {
			return Collections.emptyList();
		}
		//获取配置中配置了排除的文件,排除掉
		Set<String> allExclusions = this.autoConfigurationEntries.stream()
			.map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
		//
		Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
				.map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
				.collect(Collectors.toCollection(LinkedHashSet::new));
		processedConfigurations.removeAll(allExclusions);

		return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
				.map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
				.collect(Collectors.toList());
	}
}

getAutoConfigurationEntry

获取自动配置类,每个配置类保证成AutoConfigurationEntry对象

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
	if (!isEnabled(annotationMetadata)) {
		return EMPTY_ENTRY;
	}
	AnnotationAttributes attributes = getAttributes(annotationMetadata);
	//获取所有jar下的EnableAutoConfiguration
	List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
	//去重
	configurations = removeDuplicates(configurations);
	//获取@SpringBootApplication注解上排除的配置类
	Set<String> exclusions = getExclusions(annotationMetadata, attributes);
	//spring.autoconfigure.exclude配置的也排除
	checkExcludedClasses(configurations, exclusions);
	//排除配置类
	configurations.removeAll(exclusions);
	// 通过读取spring.factories 中的OnBeanCondition\OnClassCondition\OnWebApplicationCondition进行过滤
	configurations = getConfigurationClassFilter().filter(configurations);
	//触发事件通知
	fireAutoConfigurationImportEvents(configurations, exclusions);
	//返回筛选后的
	return new AutoConfigurationEntry(configurations, exclusions);
}

getCandidateConfigurations

获取所有jar下面META-INF/spring.factories文件中的EnableAutoConfiguration对应的集合(此集合从缓存中取,项目启动时第一次访问时,将所有配置对应的key-value加载到缓存中)

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
	//获取EnableAutoConfiguration对应的值
	List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
			getBeanClassLoader());
	Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
			+ "are using a custom packaging, make sure that file is correct.");
	return configurations;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值