@SpringBootApplication

首要先分析这个入口注解

这是@SpringBootApplication下的注解
@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) })

@SpringBootConfiguration

这是@SpringBootConfiguration下的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration//实际意义上有用的注解

表示注解相当于是@Configuration

@ComponentScan

用于扫描Component的配置注解和自动装配实现不太相关

分析一下@EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
以上注解忽略
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)

@AutoConfigurationPackage

分析该注解里的@Import(AutoConfigurationPackages.Registrar.class)

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
			register(registry, new PackageImport(metadata).getPackageName());
		}

		@Override
		public Set<Object> determineImports(AnnotationMetadata metadata) {
			return Collections.singleton(new PackageImport(metadata));
		}

	}

该类实现了ImportBeanDefinitionRegistrar和spring的后置处理器处理相关,但是我们可以知道当spring启动时会调用registerBeanDefinitions去注册bean到ioc容器中

new PackageImport(metadata).getPackageName()

把当前这个注解的路径放入这个内部类的属性中

PackageImport(AnnotationMetadata metadata) {
			this.packageName = ClassUtils.getPackageName(metadata.getClassName());
		}

回到上层register()方法

//org.springframework.boot.autoconfigure.AutoConfigurationPackages
private static final String
 BEAN = AutoConfigurationPackages.class.getName();
public static void register(BeanDefinitionRegistry registry, String... packageNames) {
//当前registry就相当于spring的一个上下文此处判断了一下这个BEAN 的信息存不存在spring中由于是jar方式启动当前肯定不在所以走else逻辑
		if (registry.containsBeanDefinition(BEAN)) {
			BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
			ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues();
			constructorArguments.addIndexedArgumentValue(0, addBasePackages(constructorArguments, packageNames));
		}
		else {
		//代码一定运行到此处
			GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
			beanDefinition.setBeanClass(BasePackages.class);
			//这里把之前new PackageImport(metadata)的放入的属性传入进来了
			beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);
			beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
			// 把这个bean注册到spring中去
			registry.registerBeanDefinition(BEAN, beanDefinition);
		}
	}

Spring Boot 3核心技术与最佳实践电子书 springboot核心包_java


所以说这个类和自动装配也不太相关往下继续走

自动装配核心@Import(AutoConfigurationImportSelector.class)

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
		ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered

该类实现了 DeferredImportSelector当这个类@Import导入进spring容器中
当执行到后置处理器时会调用该类的selectImports方法

重点分析此方法

@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		//判断有没有开启自动装配
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		//将这个类的加载器的元信息拿出来
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
				//核心
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
				annotationMetadata);
				//仅仅转换list
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

分析getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
			//EnableAutoConfiguration判断有没有
		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);
		//将一些放在ioc容器并过滤扫描出来的类主要是过滤条件注解
//@ConditionalOnWebApplication
//@ConditionalOnClass
//@ConditionalOnBean等等
		configurations = filter(configurations, autoConfigurationMetadata);
		//装配监听器
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}

获取注解信息AnnotationAttributes attributes = getAttributes(annotationMetadata);

Spring Boot 3核心技术与最佳实践电子书 springboot核心包_ide_02

getCandidateConfigurations()->loadFactoryNames()->loadSpringFactories()

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
//启动从此处获取缓存肯定是null
		MultiValueMap<String, String> result = cache.get(classLoader);
		if (result != null) {
			return result;
		}

		try {
		//从"META-INF/spring.factories";读取url
			Enumeration<URL> urls = (classLoader != null ?
					classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :			ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
			result = new LinkedMultiValueMap<>();
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				UrlResource resource = new UrlResource(url);
				//将文件load成properties
				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
				//遍历文件
				for (Map.Entry<?, ?> entry : properties.entrySet()) {
					String factoryTypeName = ((String) entry.getKey()).trim();
					for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
					//存储kv键值对
						result.add(factoryTypeName, factoryImplementationName.trim());
					}
				}
			}
			//缓存
			cache.put(classLoader, result);
			return result;
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load factories from location [" +
					FACTORIES_RESOURCE_LOCATION + "]", ex);
		}
	}

以下两个方法和上述逻辑类似直接过

filter(configurations, autoConfigurationMetadata);

spring.factroies下

Auto Configuration Import Filters
 org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=
 org.springframework.boot.autoconfigure.condition.OnBeanCondition,
 org.springframework.boot.autoconfigure.condition.OnClassCondition,
 org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

fireAutoConfigurationImportEvents(configurations, exclusions);

spring.factroies下

Auto Configuration Import Listeners
 org.springframework.boot.autoconfigure.AutoConfigurationImportListener=
 org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener