概念
能够在我们添加jar包依赖的时候,自动为我们配置一些组件的相关配置,我们屋配置或者只需要少量的配置就能运行编写的项目
核心代码解析
@SpringBootApplication
public class SpringbootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootDemoApplication.class, args);
}
}
@Target({ElementType.TYPE}) //注解的使用范围,Type表示注解可以在描述的类、接口、注解或枚举中
@Retention(RetentionPolicy.RUNTIME) //表示注解的声明周期,Runtime运行时
@Documented //表示注解可以记录在 javadoc中
@Inherited //表示可以呗子类继承该注解
@SpringBootConfiguration //表明该类为配置类
@EnableAutoConfiguration //启动自动配置
@ComponentScan( //包扫描器
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
...
}
从源码中可以看出,@SpringBootApplication注解是一个组合,前面4个是注解的元数据信息,主要是后面3个注解,@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan三个核心注解
@SpringBootConfiguration
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration //配置IOC容器
public @interface SpringBootConfiguration {
}
从这里源码中可以看出来,@SpringBootConfiguration注解内部只有一个核心注解@Configuration,该注解是Spring框架提供的,表示当前类是一个配置类,并可以被组件扫描器扫描。@SpringBootConfiguration 只是对@Configuration进行了一次封装而已
@EnableAutoConfiguration
@EnableAutoConfiguration注解表示开启自动配置功能,是SpringBoot框架最重要的注解,也是实现自动化配置的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage //自动配置包
@Import(AutoConfigurationImportSelector.class) //自动配置类扫描导入
public @interface EnableAutoConfiguration {
}
它是一个组合注解,Spring中有很多Enable开头的注解,起作用就是借助@Import来手机并注册特定场景的Bean,并加重到IOC容器。@EnableAutoConfiguration就是借助@Import来收集所有符合自动配置条件bean定义,并加载到Ioc容器的。
@AutoConfigurationPackage
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
}
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
//new PackageImport(metadata).getPackageName() 获取最外层的根目录位置
register(registry, new PackageImport(metadata).getPackageName());
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImport(metadata));
}
}
从源码看出来,核心方法就是registerBeanDefinitions(),通过Debug模式就可以发下 new PackageImport(metadata).getPackageName() 获取的就是最外层的根目录位置,也就是说,@AutoConfigurationPackage注解的主要作用就是将主程序类的所在的包及所有子包下的组件都扫描到Spring容器中
@Import(AutoConfigurationImportSelector.class)
selectImports() -> getAutoConfigurationEntry() -> getCandidateConfigurations() -> loadFactoryNames() ->
loadSpringFactories()
在这个方法中去加载了一个外部文件
@EnableAutoConfifiguration 就是从 classpath中搜寻META-INF/spring.factories配置文件,并将其中的org.springframework.boot.autoconfifigure.EnableutoConfifiguration对应的配置通过反射实例化为赌赢的标注了
@Confifiguration的JavaConfig形式的配置类,并加载到IOC容器中
总结
因此SpringBoot底层实现自动配置的步骤是:
- springboot启动
- @SpringBootApplication起作用
- @EnableAutoConfifiguration
- @AutoConfifigurationPackage 这个注解主要是 @Import(AutoConfigurationPackages.Registrar.class),通过Registrar类导入到容器中,而Registrar类的作用就是扫描主配置统计目录以及子包,并将相应的组件导入到SpringBoot创建管理的容器中
- @Import(AutoConfigurationImportSelector.class) 它通过AutoConfigurationImportSelector类导入到容器中,通过selectImports方法执行的过程,会使用内部工具类SpringFactoriesLoader查找META-INF/spring.factories进加载,是将配置类信息交给SpringFactory加载器进行一系列的容器创建过程
阿斯阿斯蒂芬