SpringBoot原理之自动配置机制详解

目录
  • 前言
  • Spring配置类
  • SpringBoot自动配置
    • 自动配置的概念
    • 自动配置的运行机制
      • 加载方式
    • SpringFactoriesLoader机制
    • SpringFactoriesLoader如何应用在自动配置中
  • 小结

前言

在当下的java生态里,SpringBoot已经成为事实上的开发标准,绝大多数人现在都是面向SpringBoot编程。SpringBoot是对Spring的进一步封装,整合了分布式系统上下游所需的各种类库和组件,并且实现了开箱即用,而这一切的底层基础就是SpringBoot的自动配置机制。

Spring配置类

Spring引入配置类是为了:1)替换冗长繁琐的配置文件,2)提供更灵活的bean定义方式。使用@Configuration注解去标记一个配置类,通过其中含有@Bean注解的方法去创建一个bean,如下代码

@Configuration
public class HelloAutoConfiguration {

    @Bean
    HelloService helloService() {
        return new HelloService;
    }

}

即为一个简单的配置类,并且定义了一个HelloService的bean。在此之上,Spring还提供了一套条件加载机制,可以去动态控制一个配置类是否被加载。通过实现org.springframework.context.annotation.Condition接口,开发者就可以自己控制配置类的加载条件,满足很多复杂的场景

SpringBoot自动配置

介绍完了Spring的配置类,我们来看看SpringBoot是怎么利用这套机制去实现自动配置的。

自动配置的概念

首先,什么是自动配置?我们看一下SpringBoot对于自动配置类的定义:

Auto-configuration classes are regular Spring @Configuration beans. They are located using the SpringFactoriesLoader mechanism (keyed against this class). Generally auto-configuration beans are @Conditional beans (most often using @ConditionalOnClass and @ConditionalOnMissingBeanannotations).

自动配置类就是一个普通的@Configuration配置类,通常会带有一些@Conditional条件注解,并且使用SpringFactoriesLoader机制去定位加载它们(并非都是如此,还有其他一些Spring固有的加载方式,比如通过@ComponentScan包扫描或者显式@Import方式都可以让它们被发现)。

自动配置的运行机制

加载方式

自动配置机制的启用是通过@EnableAutoConfiguration注解去控制的,因此需要在SpringBoot工程的入口类上启用该注解,但是通常,我们一般使用@SpringBootApplication来代替,后者是一个注解的合集,包含了一些必要的默认配置,其中就有@EnableAutoConfiguration注解,其类的注释上是这么描述的:

Indicates a Configuration class that declares one or more @Bean methods and also triggers auto-configuration and component scanning. This is a convenience annotation that is equivalent to declaring @Configuration, @EnableAutoConfiguration and @ComponentScan.

它本身既标识一个配置类,同时也开启了自动配置和组件扫描。

回到@EnableAutoConfiguration注解上,我们看一下该注解的定义

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

其中@Import(AutoConfigurationImportSelector.class)是功能生效的关键,该注解导入了AutoConfigurationImportSelector组件到Spring环境中,开启自动配置类的扫描加载工作,该类实现了接口org.springframework.context.annotation.ImportSelector

public interface ImportSelector {

    /**
     * Select and return the names of which class(es) should be imported based on
     * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
     * @return the class names, or an empty array if none
     */
    String[] selectImports(AnnotationMetadata importingClassMetadata);

   ....其他省略
}

其中selectImports方法会在Spring启动时被调用,用于返回所有的自动配置类,调用入口在org.springframework.context.annotation.ConfigurationClassParser类中,该类是Spring专门用来加载处理所有@Configuration配置类的,具体的加载细节,限于篇幅问题,就不在本文中展开说明了,读者们可自行去阅读源码,本人也许会在后续再另开一篇详细说明。接着说selectImports方法,我们来看一下自动配置类的加载过程,AutoConfigurationImportSelector对于该方法的具体实现为

    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }

isEnabled方法是一个开关,用于控制是否启用自动配置,逻辑很简单,略过不提,往下看,关键逻辑在getAutoConfigurationEntry方法中,跟下去

    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);
    }

很容易看到加载逻辑在getCandidateConfigurations方法中,后续代码是去重和过滤的过程,再往下看

    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        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去加载对应的内容,接下来我们再聊聊SpringFactoriesLoader机制是怎么回事。

SpringFactoriesLoader机制

SpringFactoriesLoader直译过来就是工厂加载机制,是Spring仿照Java的SPI机制实现的一套类加载机制,通过读取模块内的META-INF/spring.factories文件来加载类,该文件为Properties格式,其中key部分是一个Class全限定名称,可以是一个接口、抽象类或者注解等,而value部分是一个支持逗号分割的实现类列表,比如

而SpringFactoriesLoader就是Spring提供的一个用于读取解析META-INF/spring.factories文件的工具类,通过传入一个Class类型加载其对应的实现类列表。

SpringFactoriesLoader如何应用在自动配置中

介绍完了SpringFactoriesLoader,我们来研究一下SpringBoot的自动配置机制中是怎么使用它的,回到上面的getCandidateConfigurations方法中,我们看一下这一行

List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
                getBeanClassLoader());

其中第一个参数是key对应Class类型,第二个参数是用哪个ClassLoader去加载配置文件,我们看一下getSpringFactoriesLoaderFactoryClass这个方法返回的具体Class是什么

    protected Class<?> getSpringFactoriesLoaderFactoryClass() {
        return EnableAutoConfiguration.class;
    }

很简单,直接返回@EnableAutoConfiguration注解对应的class类型,那么自动配置类在META-INF/spring.factories文件中的配置方式就显而易见了,上面截图中最前面的部分

# AutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.cloud.autoconfigure.LifecycleMvcEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.WritableEnvironmentEndpointAutoConfiguration

就是对应的自动配置类了。这些被配置在此处的类都会被作为自动配置类加载到Spring中,然后进行相应的处理,发挥出每个类的功能作用。

小结

SpringBoot的自动配置机制就简单介绍到这里了,相信看官们看完了之后也都有了一些了解,当然这篇文章里还有很多相关内容没有涉及到,包括自动配置类的条件加载方式、多个类之间的加载顺序控制、排除和过滤机制,以及如何自定义自动配置类、重写框架默认行为等等,这些内容笔者会在后续的文章中再进行详细探讨。

到此这篇关于SpringBoot原理之自动配置机制的文章就介绍到这了,更多相关SpringBoot自动配置机制内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 浅析SpringBoot自动化配置原理实现

    绪论 什么是SpringBoot? Spring Boot 是所有基于 Spring 开发的项目的起点.Spring Boot 的设计是为了让你尽可能快的跑起来 Spring 应用程序并且尽可能减少你的配置文件.简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架(不知道这样比喻是否合适). SpringBoot四个主要特性 SpringBoot Starter:他将常用的依赖分组进行了整

  • 浅谈springboot自动配置原理

    从main函数说起 一切的开始要从SpringbootApplication注解说起. @SpringBootApplication public class MyBootApplication { public static void main(String[] args) { SpringApplication.run(MyBootApplication.class); } } @SpringBootConfiguration @EnableAutoConfiguration @Compon

  • 全面解析SpringBoot自动配置的实现原理

    之前一直在用SpringBoot框架,一直感觉SpringBoot框架自动配置的功能很强大,但是并没有明白它是怎么实现自动配置的,现在有空研究了一下,大概明白了SpringBoot框架是怎么实现自动配置的功能,我们编写一个最简单的自动配置功能,大概的总结一下. 一,配置属性类 其实就是值对象注入的方式去配置一些Spring常用的配置,我们编写一个最简单的配置对象. @ConfigurationProperties(prefix = "hello") //@Component //如果这

  • Spring Boot实战教程之自动配置详解

    前言 大家应该都有所了解,随着Ruby.Groovy等动态语言的流行,相比较之下Java的开发显得格外笨重.繁多的配置.低下的开发效率.复杂的部署流程以及第三方技术集成难度大等问题一直被人们所诟病.随着Spring家族中的新星Spring Boot的诞生,这些问题都在逐渐被解决. 个人觉得Spring Boot中最重要的两个优势就是可以使用starter简化依赖配置和Spring的自动配置.下面这篇文章将给大家详细介绍Spring Boot自动配置的相关内容,话不多说,来一起看看详细的介绍. 使

  • SpringBoot自动配置的实现原理

    一.运行原理 Spring Boot的运行是由注解@EnableAutoConfiguration提供的. @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({EnableAutoConfigurationImportSelector.class}) public @interface EnableAuto

  • SpringBoot原理之自动配置机制详解

    目录 前言 Spring配置类 SpringBoot自动配置 自动配置的概念 自动配置的运行机制 加载方式 SpringFactoriesLoader机制 SpringFactoriesLoader如何应用在自动配置中 小结 前言 在当下的java生态里,SpringBoot已经成为事实上的开发标准,绝大多数人现在都是面向SpringBoot编程.SpringBoot是对Spring的进一步封装,整合了分布式系统上下游所需的各种类库和组件,并且实现了开箱即用,而这一切的底层基础就是SpringB

  • SpringBoot DataSource数据源实现自动配置流程详解

    目录 一.重点概念 1.什么是DataSource数据源 2.数据库连接池 二.导入依赖 三.分析自动配置 1.DataSourceAutoConfiguration类 2.DataSourceTransactionManagerAutoConfiguration类 3.JdbcTemplateAutoConfiguration类 4.JndiDataSourceAutoConfiguration类 5.XADataSourceAutoConfiguration类 四.代码样例 一.重点概念 1

  • thinkPHP自动验证机制详解

    本文实例讲述了thinkPHP自动验证机制.分享给大家供大家参考,具体如下: array(验证字段,验证规则,错误提示,[验证条件,附加规则,验证时间]) 1.验证字段 需要验证的表单字段名称,这个字段不一定是数据库字段,也可以是表单的一些辅助字段,例如确认密码和验证码等等.有个别验证规则和字段无关的情况下,验证字段是可以随意设置的,例如expire有效期规则是和表单字段无关的. 2.验证规则 要进行验证的规则,需要结合附加规则,如果在使用正则验证的附加规则情况下,系统还内置了一些常用正则验证的

  • Spring boot中@Conditional和spring boot的自动配置实例详解

    我们知道,spring boot自动配置功能可以根据不同情况来决定spring配置应该用哪个,不应该用哪个,举个例子: Spring的JdbcTemplate是不是在Classpath里面?如果是,并且DataSource也存在,就自动配置一个JdbcTemplate的Bean Thymeleaf是不是在Classpath里面?如果是,则自动配置Thymeleaf的模板解析器.视图解析器.模板引擎 那个这个是怎么实现的呢?原因就在于它利用了Spring的条件化配置,条件化配置允许配置存在于应用中

  • Springboot @Configuration与自动配置详解

    不知道大家第一次搭SpringBoot环境的时候,有没有觉得非常简单.无须各种的配置文件,无须各种繁杂的pom坐标,一个main方法,就能run起来了.与其他框架整合也贼方便,使用EnableXXXXX注解就可以搞起来了! 所以今天来讲讲SpringBoot是如何实现自动配置的~ @SpringBootApplication: Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot需要运行这个类的main方法来启动SpringBoot应用: 先看

  • Springboot自动配置与@Configuration配置类详解

    目录 @Configuration 注意点1 注意点2 注意点3 注意点4 springboot自动配置 @Configuration 注意点1 配置类(@Configuration下的这个类)其实相当于一个工厂, 标注 @Bean 注解的方法相当于工厂方法 考虑有如下例子: @Configuration // 注意点1: 配置类其实相当于一个工厂, 标注 @Bean 注解的方法相当于工厂方法 static class MyConfig { @Bean public Bean1 bean1()

  • java开发分布式服务框架Dubbo原理机制详解

    目录 前言 Dubbo框架有以下部件 Consumer Provider Registry Monitor Container 架构 高可用性 框架设计 服务暴露过程 服务消费过程 前言 在介绍Dubbo之前先了解一下基本概念: Dubbo是一个RPC框架,RPC,即Remote Procedure Call(远程过程调用),相对的就是本地过程调用,在分布式架构之前的单体应用架构和垂直应用架构运用的都是本地过程调用.它允许程序调用另外一个地址空间(通常是网络共享的另外一台机器)的过程或函数,并且

  • Springboot启动原理和自动配置原理解析

    目录 启动原理 SpringApplication 1.初始化 2.调用run方法 自动配置原理 放本地文件夹都快吃土了,准备清理文件夹,关于Springboot的! 启动原理 @SpringBootApplication public class Start { public static void main(String[] args) { SpringApplication.run(Start.class, args); } } SpringApplication 1.初始化 public

  • 关于PyTorch 自动求导机制详解

    自动求导机制 从后向中排除子图 每个变量都有两个标志:requires_grad和volatile.它们都允许从梯度计算中精细地排除子图,并可以提高效率. requires_grad 如果有一个单一的输入操作需要梯度,它的输出也需要梯度.相反,只有所有输入都不需要梯度,输出才不需要.如果其中所有的变量都不需要梯度进行,后向计算不会在子图中执行. >>> x = Variable(torch.randn(5, 5)) >>> y = Variable(torch.rand

  • Spring Cloud应用实现配置自动刷新过程详解

    这篇文章主要介绍了Spring Cloud应用实现配置自动刷新过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 通过spring cloud 的消息总线,将配置github 等源代码仓库的变更通知到spring cloud 的所有组件. spring-bus 需要用到rabbitmq ,所以需要提前准备rabbitmq消息队列环境 配置中心调整 1.配置中心配置引用pom <dependency> <groupId>org.

随机推荐