首页 > 其他分享 >【Spring boot】自动配置的开启原理

【Spring boot】自动配置的开启原理

时间:2022-10-03 21:44:20浏览次数:52  
标签:Spring 配置 boot 开启 AutoConfigurationImportSelector 自动 EnableAutoConfiguration spr

本文结论

  • 源码使用spring boot2.6.6版本
  • 开始自动配置的核心注解:@EnableAutoConfiguration
  • @EnableAutoConfiguration中使用了@Import(AutoConfigurationImportSelector.class)。
  • AutoConfigurationImportSelector实现了DeferredImportSelector这个接口,Spring容器在启动时,会在解析完其他所有程序员定义的配置类之后,来调用AutoConfigurationImportSelector中的selectImports方法,然后把该方法返回的类名对应的类作为配置类进行解析。
  • selectImports方法中通过spi的方式,找到所有的自动配置类

spring boot开启方式

  • 一般使用@SpringBootApplication这个注解!
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class);
    }
}

@SpringBootApplication注解详细信息

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited

// 下面这三个是最核心的!可以认为@SpringBootApplication是一个三合一注解。直接写这三个注解放在核心启动类上也是可以使用的!
@SpringBootConfiguration // 标记当前是一个配置类
@EnableAutoConfiguration // 开启自动配置

// 扫描
@ComponentScan(excludeFilters = {
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM,
				classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    ......
}

开启自动配置的核心注解:@EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited

// 将主程序类所在包及所有子包下的组件到扫描到 spring 容器中。
@AutoConfigurationPackage
// 最核心的,自动配置的处理类!
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    ......
}
  • @Import(AutoConfigurationImportSelector.class),Import了自动配置的核心处理类

自动配置处理类:AutoConfigurationImportSelector

  • AutoConfigurationImportSelector实现了DeferredImportSelector这个接口,Spring容器在启动时,会在解析完其他所有程序员定义的配置类之后,来调用AutoConfigurationImportSelector中的selectImports方法,然后把该方法返回的类名对应的类作为配置类进行解析。
  • AutoConfigurationImportSelector中的selectImports会利用SpringFactoriesLoader找到所有的META-INF/spring.factories文件中key为EnableAutoConfiguration.class的value值,也就是众多自动配置类的类名。

spring.factories配置类.png

// 实现了DeferredImportSelector这个接口!
public class AutoConfigurationImportSelector
		implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
		BeanFactoryAware, EnvironmentAware, Ordered {
    ......
    // 会在@Configuration都解析完成后执行(解析完程序员自定义的类之后执行)
    // annotationMetadata这个对象是我们main方法的信息
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        // 判断是否开启自动配置:spring.boot.enableautoconfiguration配置的值为true(默认值为true)。没有开启的时候返回一个空数组。
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }

        // 获取自动配置类(spring.factories中导入的)
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
        // 返回配置类的类名
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }
    ......

    /**
     * 获取自动配置类(spring.factories中导入的)
     */
    protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        // 判断是否开启自动配置:spring.boot.enableautoconfiguration配置的值为true(默认值为true)。没有开启的时候返回一个空对象。
        if (!isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        }
        // 获取@EnableAutoConfiguration的属性值(exclude,excludeName)。作用是获取需要排除的自动配置类。
        AnnotationAttributes attributes = getAttributes(annotationMetadata);

        // 获取spring.factories文件中所有的org.springframework.boot.autoconfigure.EnableAutoConfiguration的值
        List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);

        // 按照类名去重。每个jar包都可能有spring.factories中进行了配置,内容一致进行去重。
        // 去重代码为:return new ArrayList<>(new LinkedHashSet<>(list));
        configurations = removeDuplicates(configurations);

        // 获取需要排除的自动配置类。通过@EnableAutoConfiguration中的俩个属性(exclude,excludeName)进行指定。也可以通过属性spring.autoconfigure.exclude进行配置(逗号分隔)。
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);

        // 排除操作
        checkExcludedClasses(configurations, exclusions);
        configurations.removeAll(exclusions);

        // 获取spring.factories中的AutoConfigurationImportFilter进行过滤
        // 拿到条件注解过滤:OnBeanCondition、OnClassCondition、OnWebApplicationCondition
        // 使用spring-autoconfigure-metadata.properties(编译的时候生成的文件!里面存一下条件注解对应关系)中的配置过滤。核心作用是加快启动速度!
        configurations = getConfigurationClassFilter().filter(configurations);

        // 发布一个事件,可以进行日志的打印(日志级别需要trans),展示出那些自动配置了,那些没有自动配置,因为什么导致无法进行自动配置...
        fireAutoConfigurationImportEvents(configurations, exclusions);

        // 最终的返回,全部是合格的自动配置类!
        return new AutoConfigurationEntry(configurations, exclusions);
    }

    /**
     * 获取spring.factories文件中所有的org.springframework.boot.autoconfigure.EnableAutoConfiguration的值
     */
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        // spi的方式找到spring.factories文件中所有的org.springframework.boot.autoconfigure.EnableAutoConfiguration的值
        // getSpringFactoriesLoaderFactoryClass()的逻辑是return EnableAutoConfiguration.class;
        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;
    }
}

结束语

  • 你的点赞是我提高文章质量最大的动力!!!
  • 获取更多本文的前置知识文章,以及新的有价值的文章,让我们一起成为架构师!
  • 目前已经完成了并发编程、MySQL、spring源码、Mybatis的源码。可以在公众号下方菜单点击查看之前的文章!
  • 这个公众号的所有技术点,会分析的很深入!
  • 这个公众号,无广告!!!
    作者公众号.jpg

标签:Spring,配置,boot,开启,AutoConfigurationImportSelector,自动,EnableAutoConfiguration,spr
From: https://www.cnblogs.com/zfcq/p/16751351.html

相关文章

  • Spring Cloud入门
    简介微服务是由springboot开发的一个个的模块,是一个个独立的进程springcloud是微服务全家桶springcloud通过网关调用多个负载均衡(微服务)springboot是以数字作为版本,spring......
  • 2022-10-03-SpringMVC执行流程梳理及结合源码断点调试过程源码分析
    SpringMVC执行流程梳理接口方式控制器实现流程分析控制器层代码实现控制器配置SpringMVC.xml配置文件客户端浏览器发起请求,按回车前端控制器拦截所有请求/......
  • Spring Cloud:第二章:eureka服务发现
    服务注册中心:eureka-server新建一个springboot项目:eureka-server,其pom.xml配置如下:<properties><project.build.sourceEncoding>UTF-8</project.build.sou......
  • Spring Cloud:第一章:基本介绍
    SpringCloud中文网SpringCloud是什么?SpringCloud是一系列框架的有序集合,将市面上开发得比较好的模块集成进去,进行封装,从而减少了各模块的开发成本。SpringCloud......
  • SpringBoot访问Clickhouse执行时报错:org.springframework.beans.factory.UnsatisfiedD
    1依赖信息<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"......
  • Springboot笔记
    SpringBootHelloWorld1.创建Meven工程2.引入依赖pom.xml<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</a......
  • Spring学习第一步 配置环境
    springspring配置:创建spring工程在pom.xml导入spring依赖和单元测试依赖创建pojo包--->在里面创建实体类创建applicationContext配置文件---->写bean相关......
  • springmvc-servlet.xml
    <?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"......
  • Spring-Cloud-Alibaba项目构建
    SpringCloudAlibaba项目构建版本说明由于我之前的eblog单机版本的springboot版本为2.1.4,所以之后的所有的项目都以该项目版本为基础。我们打开spring官网里面的spri......
  • SpringBoot 整合 MyBatis
    本文基于:https://www.bilibili.com/video/BV15b4y1a7yG?p=28&vd_source=cf8900ba33d057d422c588abe5d5290d在pom.xml中导入坐标<dependencies>...<!--引入MyBa......