首先 , 先看 SpringBoot 的主配置类:
@SpringBootApplicationpublicclassStartEurekaApplication{publicstaticvoidmain(String[] args){SpringApplication.run(StartEurekaApplication.class, args);}}点进 @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) })public @interface SpringBootApplication {}首先我们先来看 @SpringBootConfiguration:
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Configurationpublic @interface SpringBootConfiguration {}可以看到这个注解除了元注解以外 , 就只有一个@Configuration , 那也就是说这个注解相当于@Configuration , 所以这两个注解作用是一样的 , 它让我们能够去注册一些额外的Bean , 并且导入一些额外的配置 。
那@Configuration还有一个作用就是把该类变成一个配置类 , 不需要额外的XML进行配置 。所以@SpringBootConfiguration就相当于@Configuration 。进入@Configuration , 发现@Configuration核心是@Component , 说明Spring的配置类也是Spring的一个组件 。
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Configuration {@AliasFor(annotation = Component.class)String value default "";}继续来看下一个@EnableAutoConfiguration,这个注解是开启自动配置的功能 。
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import({AutoConfigurationImportSelector.class})public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?> exclude default {};String excludeName default {};}可以看到它是由 @AutoConfigurationPackage , @Import 这两个而组成的 , 我们先说@AutoConfigurationPackage , 他是说:让包中的类以及子包中的类能够被自动扫描到spring容器中 。
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@Import({Registrar.class})public @interface AutoConfigurationPackage {}使用 @Import 来给 Spring 容器中导入一个组件 , 这里导入的是 Registrar.class 。来看下这个Registrar:
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {Registrar {}publicvoidregisterBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName);}public Set<Object> determineImports(AnnotationMetadata metadata) {return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata));}}就是通过以上这个方法获取扫描的包路径 , 可以 debug 查看具体的值:

文章插图
那 metadata 是什么呢 , 可以看到是标注在 @SpringBootApplication 注解上的 DemosbApplication , 也就是我们的主配置类Application:

文章插图
其实就是将主配置类(即@SpringBootApplication标注的类)的所在包及子包里面所有组件扫描加载到Spring容器 。因此我们要把DemoApplication放在项目的最高级中(最外层目录) 。
看看注解@Import , @Import注解就是给Spring容器中导入一些组件 , 这里传入了一个组件的选择器
:AutoConfigurationImportSelector 。

文章插图
可以从图中看出
AutoConfigurationImportSelector 继承了 DeferredImportSelector 继承了 ImportSelector , ImportSelector有一个方法为:selectImports 。将所有需要导入的组件以全类名的方式返回 , 这些组件就会被添加到容器中 。
public String selectImports(AnnotationMetadata annotationMetadata) {if (!this.isEnabled(annotationMetadata)) {return NO_IMPORTS;} else {AutoConfigurationMetadata autoConfigurationMetadata = https://www.isolves.com/it/cxkf/kj/2021-06-11/AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry =this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations);}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Spring IOC容器对Bean实例化的过程详解源码分析
- Attention 详解深度学习中的注意力机制
- 雪莲花的做法大全家常,简单易学槐花的四种家常做法详解
- 朱元璋:我能活多久,朱元璋八字分析
- 战国时期两个字的名人,战国时期两个水利工程
- 副清风散,详解鸡冠花的药用功效与作用
- 杭白菊老字号品牌,杭白菊的生长习性
- 适合水果商标名字,0万买回商标
- 亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字
- Spring MVC 框架搭建配置方法及详解
