Springboot自动配置原理

自动配置原理

SpringBoot特点

依赖管理

  • 父项目做依赖管理

    依赖管理
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    他的父项目
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.3.2.RELEASE</version>
    </parent>
    
    依赖包的版本仲裁
    <activemq.version>5.15.13</activemq.version>
    <antlr2.version>2.7.7</antlr2.version>
    <appengine-sdk.version>1.9.81</appengine-sdk.version>
    <artemis.version>2.12.0</artemis.version>
    <aspectj.version>1.9.6</aspectj.version>
    <assertj.version>3.16.1</assertj.version>
    <atomikos.version>4.0.6</atomikos.version>
    <awaitility.version>4.0.3</awaitility.version>
    <bitronix.version>2.1.4</bitronix.version>
    <build-helper-maven-plugin.version>3.1.0</build-helper-maven-plugin.version>
    <byte-buddy.version>1.10.13</byte-buddy.version>
    <caffeine.version>2.8.5</caffeine.version>
    <cassandra-driver.version>4.6.1</cassandra-driver.version>
    <classmate.version>1.5.1</classmate.version>
    <commons-codec.version>1.14</commons-codec.version>
    ......
    
  • 加入场景启动器

    ***-spring-boot-starter 为场景启动器
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.1.3</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    

    @ConfigurationProperties

    配置文件的属性和实体类进行关联,只要容器中的组件才有这个功能

    @ConfigurationProperties(prefix = "mycar")
    public class Car {
    
        private String brand;
        private Integer price;
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    
        public Integer getPrice() {
            return price;
        }
    
        public void setPrice(Integer price) {
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Car{" +
                    "brand='" + brand + '\'' +
                    ", price=" + price +
                    '}';
        }
    }
    

    @EnableConfigurationProperties + @ConfigurationProperties或者**@Component + @ConfigurationProperties**

    @EnableConfigurationProperties(Car.class)
    //1、开启Car配置绑定功能
    //2、把这个Car这个组件自动注册到容器中
    public class MyConfig 
    {
    }
    

自动配置原理入门

@SpringBootApplication

@SpringBootConfiguration
@EnableAutoConfiguration

@SpringBootConfiguration:可以发现它本质就是一个Configuration注解,一个spring的配置类

@Configuration
public @interface SpringBootConfiguration {}

@EnableAutoConfiguration

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)

@AutoConfigurationPackage

自动配置包,给容器导入组件

@Import(AutoConfigurationPackages.Registrar.class)
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));
   }

}

image-20210320164023973

获取到包名的位置,将指定的一个包下的所有组件导入进来。

@Import(AutoConfigurationImportSelector.class)

// 给容器中批量导入组件
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    }
    AutoConfigurationEntry autoConfigurationEntry = 
        // 核心方法 利用这个方法给容器中批量导入一些组件
        getAutoConfigurationEntry(annotationMetadata);
    return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
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);
}

image-20210321193941795

默认将235个组件导入到容器中

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.loadFactoryNames读取自动配置参数

image-20210322214709407

进去loadSpringFactories函数之后显示去 缓存里面查看有没有配置参数

image-20210322214842319

关键看下面这个map的项 org.springframework.boot.autoconfigure.EnableAutoConfiguration,这个对面的就是自动的类。

image-20210322215114508

那如果没有缓存呢?紧接着执行这句话去读取META-INF/spring.factories.

classLoader.getResources()去读classsLoader这个类加载器路径下的的META-INF/spring.factories的配置文件。

image-20210322220311946

至于这个classLoader时那个类 我们回溯一下。

image-20210322222416592

进入EnableAutoConfiguration.class去看一下!

image-20210322222459270

最终发现这个类在这

image-20210322222626326

而自动配置文件就在他的类路径下面

image-20210322222708373

image-20210323224428236

image-20210323224503758

查看result的值可以发现和MybatisAutoConfiguration里面的META-INF\spring.factories 里面的配置一模一样。

210322222712.png" alt=“image-20210322222708373” style=“zoom:50%;” />

[外链图片转存中…(img-NV5cwFyS-1617804176476)]

[外链图片转存中…(img-yrgYndWg-1617804176477)]

查看result的值可以发现和MybatisAutoConfiguration里面的META-INF\spring.factories 里面的配置一模一样。

至此就可以大致知道spingboot是如何做到自动配置的,基本就是和spring.factories这个文件有关。


版权声明:本文为qq_38867101原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。