由图可知@SpringBootApplication主要由三个注解共同构成
-
@SpringBootConfiguration:该注解又由@Configuration构成即声明该类为配置类
-
@EnableAutoConfiguration
-
@ComponentScan:扫描路径
其中EnableAutoConfiguration是自动配置的主要注解它由俩个注解构成
@AutoConfigurationPackage和@Import({AutoConfigurationImportSelector.class})
@AutoConfigurationPackage注解
看的中文翻译可以猜一下 他是配置包路径的的
我们看一下它的源码
//前面四个注解为元注解
@Target({ElementType.TYPE})//表示该类为作用在类上面
@Retention(RetentionPolicy.RUNTIME)//运行时可用
@Documented
@Inherited//可以继承的该注解
@Import({AutoConfigurationPackages.Registrar.class})
public @interface AutoConfigurationPackage {
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
这里有一个@Import注解,它引入了一个类
//该类是一个静态类
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {
}
// metadata主程序的类的元信息
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
//为什么我们不用写扫描包路径,这里会得到启动类的包路径,会扫描包的下面的所有文件
AutoConfigurationPackages.register(registry, (String[])(new PackageImports(metadata)).getPackageNames().toArray(new String[0]));
}
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImports(metadata));
}
}
metadata类的内容
所以@AutoConfigurationPackage会获取当前spring的扫描路径
@Import({AutoConfigurationImportSelector.class})
这个注解引入了一个类
AutoConfigurationImportSelector类springboot2和springboot3的有些差别
但是原理相似
先扫描SPI文件
其中springboot2:/META-INF/spring.factories
springboot3扫描:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
获取所有类,然后根据@Condition等注解 排除无效的自动配置类
获取自动配置类代码
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);//获取所有的配置类,但最后不是所有都生效
//这段代码是排除一些配置项
configurations = this.removeDuplicates(configurations);//去除重复的全限类名
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.getConfigurationClassFilter().filter(configurations);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);//返回自动配置项
}
}