SpringBoot-自动装配原理-简单理解

SpringBoot自动装配是其核心,了解自动装配是学习SpringBoot所需要的。

接下来,叙述可以快速串起来的理解
目标:IOC、DI
以层级关系展示

IOC:将配置类加载到IOC
@SpringBootApplication
	@EnableAutoConfiguration
		@AutoConfigurationPackage // 会扫描将主配置类所在的包及其子包里面的组件扫描到IOC
		@Import(AutoConfigurationImportSelector.class)
			AutoConfigurationImportSelector // 继承ImportSelector接口
				String[] selectImports(annotationMetadata)
					AutoConfigurationEntry getAutoConfigurationEntry(annotationMetadata)
						List<String> getCandidateConfigurations(annotationMetadata, attributes)
							List<String> SpringFactoriesLoader.loadFactoryNames(..)
								META-INF/spring.factories // 文件包含了需要导入IOC的类全限定名
									key=value

关键地方:

@Override
// annotationMetadata 是@import所用在的注解.这里指定是@EnableAutoConfiguration
public String[] selectImports(AnnotationMetadata annotationMetadata) {
	if (!isEnabled(annotationMetadata)) {
		return NO_IMPORTS;
	}
	// 加载XXConfiguration的元数据信息(包含了某些类被生成bean条件)
	// 继续跟进这个方法调用,就会发现加载的是:spring-boot-autoconfigure
	// jar包里面META-INF的spring-autoconfigure-metadata.properties
	AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
	// 获取注解里设置的属性,在@SpringBootApplication设置的exclude,
	// excludeName属性值,其实就是设置@EnableAutoConfiguration的这两个属性值
	AnnotationAttributes attributes = getAttributes(annotationMetadata);
	// 从spring-boot-autoconfigure jar包里面META-INF/spring.factories加载配置类的名称
	// 打开这个文件发现里面包含了springboot框架提供的所有配置类
	List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);
	// 去掉重复项
	configurations = removeDuplicates(configurations);
	// 获取自己配置不需要生成bean的class
	Set<String> exclusions = getExclusions(annotationMetadata, attributes);
	// 校验被exclude的类是否都是springboot自动化配置里的类,如果存在抛出异常
	checkExcludedClasses(configurations, exclusions);
	// 删除被exclude掉的类
	configurations.removeAll(exclusions);
	// 过滤刷选,满足OnClassCondition的类
	configurations = filter(configurations, autoConfigurationMetadata);
	fireAutoConfigurationImportEvents(configurations, exclusions);
	// 返回需要注入的bean的类路径
	return StringUtils.toStringArray(configurations);
}

DI:设置默认属性值

@EnableConfigurationProperties({MybatisProperties.class})
MybatisAutoConfiguration
	@ConfigurationProperties(prefix = "mybatis") // 这就获取到properties文件的值了
	MybatisProperties{
		private String configLocation;
		private String[] mapperLocations;
		private String typeAliasesPackage;
		//...
	}

image

image

自动装配配置类名称:xxxAutoConfiguration.class

属性设置:xxxProperties.class


run(..)

初始化SpringApplication对象实列,

// 初始化SpringApplication对象
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
	// 加载classpatch文件下面的配置文件
	this.resourceLoader = resourceLoader;
	Assert.notNull(primarySources, "PrimarySources must not be null");
	this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
	// 判断是否是web运行环境
	this.webApplicationType = deduceWebApplicationType();
	// 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
	setInitializers((Collection) getSpringFactoriesInstances(
		ApplicationContextInitializer.class));
	// 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	// 获得当前执行main方法的类对象
	this.mainApplicationClass = deduceMainApplicationClass();
}
posted @ 2021-10-14 13:40  生生灯火半杯月  阅读(297)  评论(0)    收藏  举报