源码分析之SpringBoot自动装配原理

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

1、自动装配流程

@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 {
	~~~
}

2 、@SpringBootConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
	~~~
}

3、@EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
	~~~
}

自动配置导入选择器

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
		ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
	@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);
		}
	}
	// 具体用来加载自动配置累的方法
	protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		// 获取候选的配置类,即使后宫佳丽三千,也是要筛选的
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		// 根据情况自动配置需要的配置类和不需要的配置类
		configurations = removeDuplicates(configurations);
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
		configurations = getConfigurationClassFilter().filter(configurations);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		// 返回最终需要的配置
		return new AutoConfigurationEntry(configurations, exclusions);
	}
	//	去配置文件spring.factories加载enableAutoConfiguration 默认118个
	protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		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;
	}
	protected Class<?> getSpringFactoriesLoaderFactoryClass() {
		return EnableAutoConfiguration.class;
	}
	@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());
	}
	
}

自动配置实体属性

protected static class AutoConfigurationEntry {
	// 用来存储需要的配置项
	private final List<String> configurations;
	// 用来存储排除的配置项
	private final Set<String> exclusions;
	
	private AutoConfigurationEntry() {
		this.configurations = Collections.emptyList();
		this.exclusions = Collections.emptySet();
	}
}

4、往期佳文

4.1、面试系列

1、吊打面试官之一面自我介绍
2、吊打面试官之一面项目介绍
3、吊打面试官之一面系统架构设计
4、吊打面试官之一面你负责哪一块

······持续更新中······


4.2、技术系列

1、吊打面试官之分布式会话
2、吊打面试官之分布式锁
3、吊打面试官之乐观锁
4、吊打面试官之幂等性问题
5、吊打面试关之分布式事务

······持续更新中······

4.3、源码系列

1、源码分析之SpringBoot启动流程原理

······持续更新中······


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值