> 文章列表 > SpringBoot自动配置原理、手写一个xxx-spring-boot-starter

SpringBoot自动配置原理、手写一个xxx-spring-boot-starter

SpringBoot自动配置原理、手写一个xxx-spring-boot-starter

SpringBoot的自动配置是:项目中使用了一个第三方依赖,如何将第三方依赖中的Bean加载到Spring的IOC容器中,我们就可以做到无需额外的配置,直接使用第三方jar中的Bean。
SpringBoot的理念是“约定大于配置”,只要按照SpringBoot约定的规则来提供第三方的jar,SpringBoot就可以自动扫描jar中的Bean加载到IOC容器中。
先要了解SpringBoot自动配置的原理,才能手写一个xxx-spring-boot-starter

SpringBoot自动配置的原理

当我们在SpringBoot的启动类上使用了@SpringBootApplication注解后,这个注解是一个复合注解

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

查看这个注解,会看见有一个@EnableAutoConfiguration的注解,这个注解是实现SpringBoot自动配置的关键注解.

@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 {  // ...
}

继续查看@EnableAutoConfiguration注解

@Target({ElementType.TYPE})  
@Retention(RetentionPolicy.RUNTIME)  
@Documented  
@Inherited  
@AutoConfigurationPackage  
@Import({AutoConfigurationImportSelector.class})  
public @interface EnableAutoConfiguration {  // ...
}

此注解也是一个复合注解,在此注解中有一个@AutoConfigurationPackage注解,此注解能够实现此项目中启动类所在包及其子包下的Bean的自动注入
还通过@Import注解来导入一个AutoConfigurationImportSelector类,此类是实现第三方依赖中Bean注入的关键类

接下来说的是第三方依赖中要做好的配置
在第三方的依赖中,为了实现让SpringBoot自动配置本依赖,需要在此依赖中定义一个配置类,并使用@Configuration注解标注,在这个配置类中使用@Bean注解将需要注入的Bean实例化并提供出来
在此项目中的resources目录下的META-INF目录下新建spring.factories文件,此文件是一个类似于.properties的文件,通过键值对的形式,value为使用了@Configuration的配置类的全限定名
以上就是第三方依赖需要做的配置

接下来继续回到本项目,导入第三方的starter依赖后,
当项目启动后,上述的AuthoConfigurationImportSelector类就会依靠一个叫做SpringFactoriesLoader的类,此类的作用是扫描所以jar中的META-INF/spring.factories的文件,将所有文件中定义的配置类的全限定名返回,
当拿到这些第三方依赖的配置类,这些配置类中提供了要自动注入的Bean,就可以直接使用第三方依赖中的提供出来的Bean了

手写一个spring-boot-starter

1. 首先创建一个maven项目

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0</modelVersion>  <groupId>org.liumingkai</groupId>  <artifactId>kkk-spring-boot-starter</artifactId>  <version>1.0-SNAPSHOT</version>  <dependencies>  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter</artifactId>  <version>2.7.10</version>  </dependency>  </dependencies>  <properties>  <maven.compiler.source>8</maven.compiler.source>  <maven.compiler.target>8</maven.compiler.target>  </properties>  </project>

2.创建一个需要自动注入的Bean

package com.liumingkai.service;  import org.springframework.beans.factory.annotation.Value;  /**  * @author 刘明凯  * @version 0.0.1  * @date 2023年4月23日 19:50  */public class SayHello {  @Value("Mingkai Liu")  private String name;  public void sayHello(){  System.out.println("Hello , My name is " +  name);  }  }

3.创建此项目的配置类,将需要注入的类提供出去

package com.liumingkai.auto;  import com.liumingkai.service.SayHello;  
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  /**  * @author 刘明凯  * @version 0.0.1  * @date 2023年4月23日 19:50  */@Configuration  
public class MyConfiguration {  @Bean  public SayHello sayHello(){  SayHello sayHello = new SayHello();  return sayHello;  }  }

4. 在META-INF/spring.factories文件中指明该项目配置类的全限定名

org.springframework.boot.autoconfigure.EnableAutoConfiguration= com.liumingkai.auto.MyConfiguration

5.将项目打包到本地仓库(利用Maven的install命令)
6.在需要引用的项目中导入此依赖

<dependency>  <groupId>org.liumingkai</groupId>  <artifactId>kkk-spring-boot-starter</artifactId>  <version>1.0-SNAPSHOT</version>  
</dependency>

测试自动注入是否成功

package com.liumingkai;  import com.liumingkai.service.SayHello;  
import org.junit.jupiter.api.Test;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.boot.test.context.SpringBootTest;  @SpringBootTest  
class SpringBootTestMystaterApplicationTests {  @Autowired  private SayHello hello;  @Test  void contextLoads() {  hello.sayHello();  }  }

运行结果,发现成功注入
SpringBoot自动配置原理、手写一个xxx-spring-boot-starter