springBoot启动流程简要说明-启动注解

108 阅读3分钟

摘要

大家好,我是小编小八,好久不见,今天开始我将陆续分享我自己对springBoot的启动流程一些源码的理解,一共会分好几个篇章,大致目录就在下面啦,有什么说错的请各位jym批评指正哈!

目录一栏

  1. 启动注解
  2. 程序启动
  3. 环境准备
  4. 创建跟准备spring容器
  5. 刷新spring容器

这节我只讲注解的功能是什么,至于功能的具体实现我会在后面的章节里讲到

启动注解

SpringBoot启动必须要在main所在类上加这个注解\

@SpringBootApplication

他定义了spring扫描bean的范围、bean排除拦截器 同时它是多个功能注解的集合,主要包含了如下三个注解

@SpringBootConfiguration

这个注解目前没有实际的功能属性,继承了@Configuration注解也是一个配置类,主要作为一个springBoot配置标识

@ComponentScan

@ComponentScan(excludeFilters = {
      @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

这个注解是spring框架中用于设置扫描bean扫描范围的,同时它也可以设置用于设置bean排除拦截器,这里就内置了两个拦截器
TypeExcludeFilter:用于获取bean工厂中设置的自定义TypeExcludeFilter,进行批量排除校验 AutoConfigurationExcludeFilter:用于排除掉一些配置了@Configuration注解但是已经在EnableAutoConfiguration集合中的class

@EnableAutoConfiguration

这个注解是springBoot进行做自动化配置的核心方法,点进去后发现他里面最核心就是@import注解,内置了如下两个类

AutoConfigurationImportSelector.class

设置的这个类继承了ImportSelector接口,主要的作用是会扫描所有jar包的META-INF目录下的spring.factories文件中的需要自动配置的configuration类全部获取出来,给到spring容器进行处理

public String[] selectImports(AnnotationMetadata annotationMetadata) {
   // 是否需要进行自动配置
   if (!isEnabled(annotationMetadata)) {
      // 不需要,返回空数组
      return NO_IMPORTS;
   }
   // 获取自动配置元数据,META-INF目录的spring-autoconfigure-metadata.properties文件
   AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
         .loadMetadata(this.beanClassLoader);
   // 获取当前注解中的EnableAutoConfiguration注解信息
   AnnotationAttributes attributes = getAttributes(annotationMetadata);
   // 获取可选的配置类
   List<String> configurations = getCandidateConfigurations(annotationMetadata,
         attributes);
   // 保持原顺序的去重,这个实现利用到了集合特性有兴趣的可以看看
   configurations = removeDuplicates(configurations);
   // 用排除拦截器过滤掉class
   Set<String> exclusions = getExclusions(annotationMetadata, attributes);
   checkExcludedClasses(configurations, exclusions);
   configurations.removeAll(exclusions);
   // 过滤一些被条件限制的配置,如:ConditionalOnClass、ConditionalOnMissingClass
   configurations = filter(configurations, autoConfigurationMetadata);
   // 触发自动配置类引入事件
   fireAutoConfigurationImportEvents(configurations, exclusions);
   return StringUtils.toStringArray(configurations);
}

获取可选的配置类具体实现

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
      AnnotationAttributes attributes) {
   // 从META-INF目录的spring.factories文件获取key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的value值,根据,分成数组
   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;
}

SpringFactoriesLoader.loadFactoryNames这个方法spring spi的核心入口,有兴趣的可以去了解下spring spi机制

AutoConfigurationPackages.Registrar.class

另一个import类,这个类继承了ImportBeanDefinitionRegistrar接口,这个类的作用是将启动类的包路径信息设置到BasePackages类中,这样spring就是自动将启动类目录及子目录都看作是扫描范围了

结束语

启动注解部分就简单的讲完啦,以上就是小编本人理解的实现原理,有些地方可能还是有点笼统,如果有疑问的,可以在评论区跟我讨论哈!!