自己如何写一个 SpringBoot 第三方依赖包?

本文 SpringBoot 为 2.3.4版本

1、SpringBoot特点,了解自动配置原理

1.1、依赖管理

  • 父项目做依赖管理:

<!-- 依赖管理 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.4.RELEASE</version>
</parent>

		
<!-- ↓↓↓ spring-boot-starter-parent 的父项目 ↓↓↓ -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.3.4.RELEASE</version>
</parent>

<!-- spring-boot-dependencies依赖,几乎声明了所有在开发中常用的依赖及版本号,自动版本仲裁机制 -->
  • 开发导入starter场景启动器:

    1. 见到很多 spring-boot-starter-* :*代表某种场景
    2. 只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
    3. SpringBoot所有支持的场景,传送门: https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
    4. 见到的 *-spring-boot-starter*就是第三方为我们提供的与Spring整合的依赖。
    5. 所有场景启动器最底层的依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.3.4.RELEASE</version>
    <scope>compile</scope>
</dependency>
  • 无需关注版本号,自动版本仲裁
1、引入依赖默认都可以不写版本,比如:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2、引入非版本仲裁的jar,要写版本号。
  • 可以修改默认版本号
1、查看 spring-boot-dependencies 里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置
<properties>
    <mysql.version>5.1.43</mysql.version>
</properties>

1.2、自动配置Web依赖

  • 自动配好Tomcat

    • 引入spring-boot-starter-web坐标,该pom坐标中包含有spring-boot-starter-tomcat的依赖,所以启动的时候可以选择tomcat来作为web服务器
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • 默认的包结构:

    • 主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
    • 无需以前的包扫描配置
    • 想要改变扫描路径,@SpringBootApplication(scanBasePackages="com.atguigu")
  • 或者在主启动类中使用 @ComponentScan 注解,指定扫描路径。

@SpringBootApplication 注解
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")
  • 各种配置拥有默认值

    • 默认配置最终都是映射到某个类上,如:MultipartProperties
    • 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
  • 按需加载所有自动配置项

    • 非常多的starter
    • 引入了某个场景的依赖,这个场景的自动配置才会开启,并不是说所有的配置类都会生效。
    • SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面

模拟与SpringBoot整合的第三方依赖

自己如何写一个 SpringBoot 第三方依赖包?

整体结构

  • 新建项目名叫 xxx-starter 和 xxx-autoconfigure 的模块
    • xxx-starter 项目负责在 pom.xml 中引入各种各样的依赖,若别人想使用这个第三方依赖的某个功能,直接引入 xxx-starter 的坐标即可。xxx-starter 项目引入了 xxx-autoconfigure 项目依赖。
    • xxx-autoconfigure 项目负责对这个第三方依赖做些初始化自动配置的操作(比如注册 配置类、xxxProperties… 到容器中)

starter项目

  • 在 pom.xml 中引入 autoconfigure 的坐标
<dependencies>
    <dependency>
        <groupId>com.calm</groupId>
        <artifactId>calm-hello-spring-boot-autoconfigure</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

autoconfigure项目

  • 在 pom.xml 中添加需要的依赖
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.4.RELEASE</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
</dependencies>
  • Properties
// 去配置文件中找以“prefix属性值”为前缀的属性,将他们的值绑定到该类上
@ConfigurationProperties(prefix = "calm.hello")
public class HelloProperties {

    private String prefix;
    private String suffix;

    public String getPrefix() {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public String getSuffix() {
        return suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }
}
  • service
public class HelloService {
    
    // 注入属性
    @Autowired
    private HelloProperties helloProperties;

    public String sayHello(String name){
        return helloProperties.getPrefix() + "--" + name + "--" + helloProperties.getSuffix();
    }
    
}
  • config配置类
@Configuration
// 开启HelloProperties类的配置绑定功能,将绑定好之后放入到IOC容器中。
@EnableConfigurationProperties(HelloProperties.class) 
public class HelloServiceAutoConfiguration {

    // 判断若IOC容器中没有 HelloService类型的Bean,才会将HelloService注册到容器中。
    // 目的是如果用户自定义了一个HelloService,那就用用户自定义的,如果没有自定义,那就用我们的。
    @ConditionalOnMissingBean(HelloService.class)
    @Bean
    public HelloService helloService(HelloProperties helloProperties){
        // 从容器中拿到 HelloProperties 进行设置值。
        helloProperties.setPrefix("注册Bean到容器中。");
        return new HelloService();
    }

}
  • 项目中新建 META-INF/spring.factories文件

    • 其中 EnableAutoConfiguration 的值表示项目在启动时要加载的自动配置类
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.calm.config.HelloServiceAutoConfiguration
    

测试

新建个项目,引入自定义的starter依赖,autoconfigure会自动引入进来,依赖传递。

<dependency>
    <groupId>com.calm</groupId>
    <artifactId>calm-hello-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
  • 再新建一个applicaiton.yaml 配置文件
calm:
  hello:
    prefix: 配置前缀
    suffix: 配置后缀
  • 在test包下写一个测试类
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringBootStarterAutoConfiguration {

    @Autowired
    private HelloService helloService;

    @Test
    public void sayHello(){
        System.out.println(helloService.sayHello("张三"));
    }

}
上一篇:day 93 登陆注册模态框、 登陆注册接口分析、 多方式登陆方式、 cookies修改页面登陆状态、 前台注销、 手机号是否存在接口、 腾讯云短信服务


下一篇:第二章:(5)自动配置原理