@SpringBootApplication解析

注解中主要的三个注解

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

1、@SpringBootConfiguration

@Configuration。代表当前是一个配置类

2、@ComponentScan

指定扫描哪些,Spring注解;

3、@EnableAutoConfiguration

两个重要注解

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

1、@AutoConfigurationPackage

Registrar是把某一个包下的所有组件注册到容器中
利用Registrar给容器中导入一系列组件、将MainApplication所在包下的所有组件导入进来。
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}

/**
* {@link ImportBeanDefinitionRegistrar} to store the base package from the importing
* configuration.
*
* 用于存储来自导入配置的基本包
*/
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
}

@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImports(metadata));
}

}

2.@Import(AutoConfigurationImportSelector.class)

    返回要注册组件的集合
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); }
   /**
     * Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}
     * of the importing {@link Configuration @Configuration} class.
     * @param annotationMetadata the annotation metadata of the configuration class
     * @return the auto-configurations that should be imported
     */

// 根据路径获取所有组件 根据条件筛选不注册的组件 最后包装要注册的组件 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); }
1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2、调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
3、利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件
4、从META-INF/spring.factories位置来加载一个文件。
    默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
例如 spring-boot-autoconfigure-2.7.1.jar!/META-INF/
spring.factories

给容器中导入的组件总量

按需开启自动配置项

虽然我们所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration
按照条件装配规则(@Conditional),最终会按需配置。

底层的一个默认配置写法

        @Bean
        @ConditionalOnBean(MultipartResolver.class)  //容器中有这个类型组件
        @ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
        public MultipartResolver multipartResolver(MultipartResolver resolver) { //resolver 回去容器中找
            // 给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
            // SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
            // Detect if the user has created a MultipartResolver but named it incorrectly
            return resolver;
        }
给容器中加入了文件上传解析器;

 

SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先

@Bean
    @ConditionalOnMissingBean // 没有时在注册到容器中
    public CharacterEncodingFilter characterEncodingFilter() {

    }

总结:

  • SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
  • 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
  • 生效的配置类就会给容器中装配很多组件
  • 只要容器中有这些组件,相当于这些功能就有了
  • 定制化配置
    • 用户直接自己@Bean替换底层的组件
    • 用户去看这个组件是获取的配置文件什么值就去修改。

xxxxxAutoConfiguration ---> 组件 ---> xxxxProperties里面拿值 ----> application.properties

最佳实践

  • 引入场景依赖
  • 查看自动配置了哪些(选做)
    • 自己分析,引入场景对应的自动配置一般都生效了
    • 配置文件中debug=true开启自动配置报告。Negative(不生效)\Positive(生效)
  • 是否需要修改
    • 参照文档修改配置项
    • 自定义加入或者替换组件
      • @Bean、@Component。。。
    • 自定义器 XXXXXCustomizer

例如:Spring banner

 

posted @ 2022-07-10 09:09  Dabo丶  阅读(84)  评论(0编辑  收藏  举报