SpringBoot自动装配原理以及run执行过程
AutoConfigurationPackage注解分析
AutoConfigurationPackage注解的作用是会把springbootApplication注解标注的类所在包名拿到,并且对该子包进行扫描
/**
* {@link ImportBeanDefinitionRegistrar} to store the base package from the importing
* configuration.
*/
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
registerBeanDefinitions方法中,metadata就是标记注解的元数据信息 我们可以在这里下断点调试一下

可以发现确实获取到了当前启动类的包名,而且看下面metadata中的信息确实获取到了启动类

public static void register(BeanDefinitionRegistry registry, String... packageNames) {
if (registry.containsBeanDefinition(BEAN)) {
BasePackagesBeanDefinition beanDefinition = (BasePackagesBeanDefinition) registry.getBeanDefinition(BEAN);
beanDefinition.addBasePackages(packageNames);
}
else {
registry.registerBeanDefinition(BEAN, new BasePackagesBeanDefinition(packageNames));
}
}
在具体的这个register方法中,将这个报名封装成了一个BeanDefinition对象并且注册到了IOC容器中
AutoConfigurationImportSelector分析
我们进入到AutoConfigurationImportSelector类中的selectImports方法,这个方法就是告诉springboot需要导入哪些组件
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
在这个方法里,加载配置文件,从中获取所有支持自动装配的类的条件,springboot会将收集好的@Configuration进行一次过滤进而剔除不满足条件的配置类。我们进getAutoConfigurationEntry这个方法看一下
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);
}
这里的getCandidateConfigurations是重点,用来获取默认支持的自动配置类列表,我们进去详细看一下
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;
}
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = cache.get(classLoader);
if (result != null) {
return result;
}
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());
}
}
}
// Replace all lists with unmodifiable lists containing unique elements
result.replaceAll((factoryType, implementations) -> implementations.stream().distinct()
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
