一文搞懂 springboot 自动配置原理

目录

1、自动配置原理(基于springboot 3.0 版本)

2、自动配置中注解

3、自定义 starter 

3.1、定义 pom.xml 文件

3.2、定义属性类

3.3、编写自动配置类,使用容器中的属性类读取配置文件中的属性值。 

3.4、定义实体类

3.5、编写自动配置文件

4、引入自定义的 starter ,并且测试自动配置功能

4.1、pom.xml

4.2、配置文件 application.yml

 4.3、主启动类

        SpringBoot 的核心原理就是自动配置,其所有的配置类都是由 spring-boot-autoconfiguration这个模块提供的,自动配置类一般是以 ***AutoConfiguration命名,自动配置类需要注册到自动配置文件中。

自动配置文件:

1)、在 springboot 2.7 之前,自动配置文件在 META-INF/spring.factories (在 springboot 2.7 版本中宣布废弃了)

2)、在 springboot 3.0 之前,老的自动配置文件依旧支持,为了向后兼容;在 springboot 3.0 之后,正式废除,采用新的自动配置文件。新的自动配置文件为:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports。

1、自动配置原理(基于springboot 3.0 版本)

springboot 自动配置原理使用是 @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 {};
}

1)、@AutoConfigurationPackage:注册需要自动配置的包,如果不指定就是当前注解所在类的包。
2)、@Import({AutoConfigurationImportSelector.class}):导入AutoConfigurationImportSelector配置类。

AutoConfigurationImportSelector配置类实现了ImportSelector 接口 

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

// ========================
protected 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 AutoConfigurationEntry(configurations, exclusions);
     }
 }

getAutoConfigurationEntry 方法进入  getCandidateConfigurations 方法。

// 自动配置文件路径
private static final String LOCATION = "META-INF/spring/%s.imports";

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
     List<String> configurations = ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).getCandidates();
     Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.");
     return configurations;
}

// ImportCandidates.load 方法
public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
    Assert.notNull(annotation, "'annotation' must not be null");
    ClassLoader classLoaderToUse = decideClassloader(classLoader);
    String location = String.format("META-INF/spring/%s.imports", annotation.getName());
    Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
    List<String> importCandidates = new ArrayList();

    while(urls.hasMoreElements()) {
        URL url = (URL)urls.nextElement();
        importCandidates.addAll(readCandidateConfigurations(url));  
    }

    return new ImportCandidates(importCandidates);  // 返回类型:List<String>
}

最后得到将要自动注册到容器中的 对象列表。

2、自动配置中注解

1)、@AutoConfiguration : 是 @Configuration(proxyBeanMethods = false),@AutoConfigureBefore,@AutoConfigureAfter 三者的组合,带有这个注解就表示这个是个自动配置类。

2)、@ConditionOn* : 这是一种条件注解,表示在满足指定条件时才会进行自动配置。主要有:@ConditionOnClass,@ConditionOnBean,@ConditionOnProperty;@ConditionOnMissingClass,@ConditionOnMissingBean,@ConditionOnMissingProperty。

3)、排除某个自动配置:@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})。

4)、@SpringBootConfiguration:替代 @Configuration 注解。
5)、@EnableAutoConfiguration:开启自动配置。

这些是主要的注解,足以看懂源码。

3、自定义 starter 

自定义一个 starter ,并且使用自动配置功能,帮助彻底搞懂自动配置原理。

3.1、定义 pom.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.test</groupId>
    <!--    第三方starter 定义的方法  -->
    <artifactId>test-spring-boot-starter</artifactId>
    <version>1.0</version>
    <name>autoconfiguration</name>
    <description>autoconfiguration</description>
    <properties>
        <java.version>17</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>3.0.0</spring-boot.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>
3.2、定义属性类
// 属性类
@Data
@ConfigurationProperties(prefix = "weilong.param")
public class TestProperties {

    private String name;
    private Integer age;
}
3.3、编写自动配置类,使用容器中的属性类读取配置文件中的属性值。 
@AutoConfiguration
@ConditionalOnProperty(prefix = "test.enable", name = "isauto", havingValue = "true") // 决定是否被自动注册
@EnableConfigurationProperties({TestProperties.class}) // 将属性类加载到容器
public class TestAutoConfiguration {
    @Bean
    public TestClass testClass(TestProperties testProperties){
        TestClass testClass = new TestClass();
        testClass.setAge(testProperties.getAge());
        testClass.setName(testProperties.getName());
        return testClass;
    }
}
3.4、定义实体类
@Data
public class TestClass {
    private String name;
    private Integer age;
    public String test(){
        return "hello "+ name + " autoConfiguration: " + age;
    }
}
3.5、编写自动配置文件

在 resources 目录下创建 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,内容如下。

com.test.autoconfiguration.test.TestAutoConfiguration 
4、引入自定义的 starter ,并且测试自动配置功能

新建一个模块,导入自定义的 starter 

4.1、pom.xml
<dependencies>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
   </dependency>
   <dependency>
      <groupId>com.test</groupId>
      <artifactId>test-spring-boot-starter</artifactId>
      <version>1.0</version>
      <scope>compile</scope>
   </dependency>
</dependencies>
4.2、配置文件 application.yml
test:
  enable:
    isauto: true  # 决定是否开启自动配置
  param:
    name: test
    age: 1
 4.3、主启动类

启动主启动类,发现 TestClass 不必导入就可以直接使用,说明已经被自动配置。

@SpringBootApplication
@Slf4j
public class AutoCOnfigurationtestApplication {
    public static void main(String[] args) {
        SpringApplication.run(AutoCOnfigurationtestApplication.class, args);
    }

    @Bean
    public CommandLineRunner commandLineRunner(TestClass testClass){
        return args -> log.info(testClass.test());
    }
}

总结:以上是自动配置原理解读,通过手写 starter,注册自动配置类 ,进一步理解自动配置原理,还有很多内容没有涉及,需要阅读源码进一步深入细节。

        本人是一个从小白自学计算机技术,对运维、后端、各种中间件技术、大数据等有一定的学习心得,想获取自学总结资料(pdf版本)或者希望共同学习,关注微信公众号:it自学社团。后台回复相应技术名称/技术点即可获得。(本人学习宗旨:学会了就要免费分享)

  • 43
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Spring Boot自动配置原理是通过在类路径中搜索特定的类,并根据它们发现的内容自动配置应用程序。它使用@EnableAutoConfiguration注解和@Configuration注解将类路径中的类和jar文件与Spring应用程序上下文进行关联。 ### 回答2: Spring Boot自动配置原理是通过条件注解实现的。 Spring Boot在启动时会通过@SpringBootApplication注解扫描类路径下的所有组件,并自动配置这些组件的实例。在自动配置过程中,Spring Boot使用了条件注解来判断是否需要配置某个组件。 条件注解可以根据一些条件来决定是否启用某个组件的配置。例如,@ConditionalOnClass注解可以根据类路径下是否存在指定的类来决定是否启用某个组件的配置。@ConditionalOnProperty注解可以根据配置文件中的属性值来决定是否启用某个组件的配置。 在自动配置过程中,Spring Boot会通过条件注解判断是否需要配置某个组件,如果需要配置,则会根据组件的配置类和属性值创建对应的实例。如果没有需要配置的组件,Spring Boot会跳过自动配置过程。 通过自动配置Spring Boot简化了应用的搭建过程,减少了开发人员的配置工作。开发人员只需要在配置文件中设置一些属性,或者添加一些指定的依赖,Spring Boot就能根据这些信息自动配置应用所需的组件。 总之,Spring Boot自动配置原理是通过条件注解来判断是否需要配置某个组件,根据配置类和属性值创建对应的实例,从而简化了应用的配置过程。这个原理使得开发人员能够更加专注于业务逻辑的开发,提高了开发效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知其_所以然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值