一文搞懂 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 configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
        configurations = this.removeDuplicates(configurations);
        Set 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 getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
     List 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 urls = findUrlsInClasspath(classLoaderToUse, location);
    List importCandidates = new ArrayList();

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

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

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

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 文件


    4.0.0
    com.test
    
    test-spring-boot-starter
    1.0
    autoconfiguration
    autoconfiguration
    
        17
        UTF-8
        UTF-8
        3.0.0
    
    
        
            org.springframework.boot
            spring-boot-starter
        
        
            org.projectlombok
            lombok
        
    

    
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.8.1
                
                    17
                    17
                    UTF-8
                
            

        
    


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

   
      org.springframework.boot
      spring-boot-starter
   
   
      com.test
      test-spring-boot-starter
      1.0
      compile
   
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自学社团。后台回复相应技术名称/技术点即可获得。(本人学习宗旨:学会了就要免费分享)

一文搞懂 springboot 自动配置_第1张图片

你可能感兴趣的:(java技术,SpringBoot,spring,boot,java,spring)