首页 > 其他分享 >Spring Boot自动配置原理揭秘

Spring Boot自动配置原理揭秘

时间:2023-12-31 21:02:04浏览次数:27  
标签:Spring 配置 Boot annotationMetadata 自动 揭秘 configurations

(自动配置原理)

概述


  Spring Boot 是一个用于创建独立的、生产级别的 Spring 应用程序的框架。它极大地简化了 Spring 应用程序的开发过程,其中一个关键的功能就是自动配置(Auto-Configuration)。

  自动配置可以根据项目需求自动配置各种服务和组件,它可以帮助开发者在不需要显式配置的情况下,快速地构建一个运行的应用程序。

  自动配置是 Spring Boot 的一个核心特性,它通过分析项目的依赖和环境,自动地为应用程序配置 Spring 配置文件。这意味着开发者无需手动配置大量的 Spring Bean,Spring Boot 会根据环境和项目的依赖来智能地为应用程序创建所需的 Bean。

原理


  Spring Boot的自动配置原理基于Java的反射机制和Spring的IoC容器。它通过读取项目中的配置文件(如application.properties或application.yml),根据配置信息自动创建和配置各种服务。

可以概括为以下几个==步骤:==

Spring Boot Starter


  Spring Boot 项目通常依赖于所谓的 "Starters",这是一组预定义了常用库的依赖集合。Starters 包含了应用程序所需的所有依赖,比如 Web Starter 会包含用于构建 Web 应用程序的所有必要库。

spring.factories 文件


  在每个 Starter 的 META-INF/spring.factories 文件中,定义了一系列的自动配置类。这些自动配置类会在应用程序启动时被 Spring Boot 自动扫描和加载。

@ConditionalOnX 注解


  在自动配置类中,通常会使用 @ConditionalOnX 注解来控制该自动配置是否生效。这个注解会根据特定的条件(比如类是否在类路径中、特定的 Bean 是否存在等)来决定是否应用这个配置。

配置 Bean


  自动配置类会定义一些必要的 Bean,并使用 @Configuration 注解将它们标记为配置类。这些 Bean 会在 Spring 上下文中被自动注册。

配置属性


  自动配置类还可以通过读取 application.propertiesapplication.yml 文件中的属性来自定义它们的行为。这样,开发者可以根据需要进行定制。

源码剖析


Spring Boot 应用的启动类一般均位于src/main/java根路径下

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

复合Annotation


  @SpringBootApplication开启组件扫描和自动配置,而SpringApplication.run则负责启动引导应用程序。@SpringBootApplication是一个复合Annotation,它将三个有用的注解组合在一起:

@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就相当于@Configuration,它是 Spring 框架的注解,标明该类是一个JavaConfig配置类。而@ComponentScan启用组件扫描。

@EnableAutoConfiguration


  @EnableAutoConfiguration注解表示开启 Spring Boot 自动配置功能,Spring Boot 会根据应用的依赖、自定义的 bean、classpath 下有没有某个类 等等因素来猜测你需要的 bean,然后注册到 IOC 容器中。   @EnableAutoConfiguration是如何推算出需求的?首先来看下它的定义:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    // ...省略内容
}

  ==重点关注点==在@Import({AutoConfigurationImportSelector.class}) @Import注解用于导入类,并将这个类作为一个 bean 的定义注册到容器中,这里它将把EnableAutoConfigurationImportSelector作为 bean 注入到容器中,而这个类会将所有符合条件的@Configuration配置都加载到容器中。

  查看EnableAutoConfigurationImportSelector代码可以看到:

AutoConfigurationImportSelector


  AutoConfigurationImportSelector 实现了DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered 这些接口。核心代码为

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    //...
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }
}

再来具体看getAutoConfigurationEntry 方法具体是如何判断哪些是需要导入的。

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            configurations = this.removeDuplicates(configurations);
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = this.getConfigurationClassFilter().filter(configurations);
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }

  annotationMetadata 参数是一个元数据接口,它提供了对注解元数据的访问权限,通常用于在运行时检查类上的注解。

  getAutoConfigurationEntry(annotationMetadata)方法会根据传入的 annotationMetadata返回一个 AutoConfigurationEntry对象。

  AutoConfigurationEntry是一个内部类,用于封装自动配置项的信息,包括该自动配置项的类名、条件(Conditions)等信息。

  通过获取到的 autoConfigurationEntry对象,Spring Boot 就能够知道哪些自动配置类需要被导入,从而将它们注册到 Spring 上下文中。

标签:Spring,配置,Boot,annotationMetadata,自动,揭秘,configurations
From: https://blog.51cto.com/u_16111319/9050162

相关文章

  • Spring如何利用三级缓存解决单例Bean的循环依赖
    循环依赖:就是N个类循环(嵌套)引用。通俗的讲就是N个Bean互相引用对方,最终形成闭环。用一幅经典的图示可以表示成这样(A、B、C都代表对象,虚线代表引用关系):注意:其实可以N=1,也就是极限情况的循环依赖:自己依赖自己可以设想一下这个场景:如果在日常开发中我们用new对象的方式,若构造......
  • 基于Spring Boot2.x 设置 Spring Cloud Gateway 限流(令牌桶模式)
    参考https://blog.csdn.net/yuanchangliang/article/details/109579705https://blog.csdn.net/qq_38380025/article/details/102968559https://blog.csdn.net/ctwy291314/article/details/129425512https://blog.csdn.net/wxxiangge/article/details/95024214https://blog......
  • Spring学习记录之引入外部属性配置文件
    Spring学习记录之引入外部属性配置文件前言这篇文章是我第二次学习b站老杜的spring相关课程所进行的学习记录,算是对课程内容及笔记的二次整理,以自己的理解方式进行二次记录,其中理解可能存在错误,欢迎且接受各位大佬们的批评指正;关于本笔记,只是我对于相关知识遗忘时快速查阅了解......
  • SpringBoot接入Mybatis-Flex
    相信不少的伙伴在日常开发中应该都用过MyBatis增强框架吧,目前来说国内用的比较多的无非就是MyBatis-Plus,那么今天我再给大家介绍一款新的MyBatis增强框架,它就是MyBatis-Flex。那么这个框架到底怎么样呢,跟MyBatis-Plus有什么不一样的呢,下面我们先来看下它的介绍,这是官网的一段介......
  • SpringBoot2 整合 Eurkea 实例
    文章目录1.概述2.注册示例2.1工程目录2.2引入依赖2.3启动类2.4配置文件2.5启动服务注册中心3.服务提供者(eurekaclient)实例3.1工程目录3.2引入依赖3.3Java源文件3.5配置文件3.6启动服务提供者参考文献1.概述Eurkea主要负责服务治理功能。服务治理主要用来实现各......
  • SpringBoot2 整合 SpringCloud Feign 实例
    文章目录1.简介2.工程实例2.1注册中心springcloud-study-eureka-server2.1.1依赖pom.xml2.1.2配置文件application.properties2.1.3启动类EurekaServerApplication.java2.2服务提供者springcloud-study-hello-service2.2.1依赖pom.xml2.2.2配置文件application.ym......
  • SpringBoot2 整合 SpringCloud 的 Hystrix断路器 实例
    文章目录1.概述2.短路器3.SpringFeign使用Hystrix断路器3.1工程实例3.2修改Fegin模块3.3测试运行参考文献1.概述微服务架构中服务之间互相调用,单个服务通常会集群部署,由于网络等原因,服务不能保证100%可用,如果单个服务出现问题会出现请求的堆积,Servlet容器的线程资源......
  • SpringBoot2 整合 Redis 实例,实现写入和读取的操作
    1.启动RedisServer启动redisserver,如下图所示,端口号6379:2.工程实例2.1工程目录工程目录如下图所示:2.2pom.xml引入依赖:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>......
  • Spring 事务失效的情况
    1.数据库引擎不支持事务以MySQL为例,MyISAM存储引擎不支持事务,InnoDB引擎支持事务。2.异常被catch执行以下测试方法,数据成功插入,调用test方法没有回滚。@Override@Transactional(rollbackFor=Exception.class,propagation=Propagation.REQUIRED)publicvoid......
  • Spring Boot2.x 集成 OpenFeign 实现 Hystrix 熔断降级与 Ribbon 负载均衡配置
    参考https://blog.csdn.net/zhangchaoyang/article/details/123453616https://blog.csdn.net/u010277958/article/details/88744263https://blog.csdn.net/iwlnner/article/details/110090595https://cloud.tencent.com/developer/article/2225692https://blog.csdn.net/z......