您现在的位置是:首页 >其他 >SpringBoot自动配置原理、手写一个xxx-spring-boot-starter网站首页其他

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

秋天code 2023-06-06 12:00:02
简介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();  
    }  
  
}

运行结果,发现成功注入

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。