拒绝花里胡哨,极简springboot starter及原理

拒绝花里胡哨,极简springboot starter及原理

解决方案goocz2025-02-01 11:20:3924A+A-

SpringBoot针对日常企业应用场景提供了各种spring-boot-starter依赖模块,所有这些依赖模块都遵循着约定俗成的默认配置,并允许我们调整这些配置,即遵循“约定大于配置”的理念。SpringBoot通过AutoConfiguration模块自动装配官方(以spring-boot-starter-xxx方式命名)、第三方以及自定义(以xxx-spring-bbot-starter方式命名)的starter.

当我们向其他项目提供jar包时,可自定义为starter,SpringBoot项目即可像自动加载spring-boot-starter-jdbc、spring-boot-starter-web等一样自动加载您的starter,下面即为一个最简单的自定义starter例子和原理介绍:

1. Pom依赖

<?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>com.zhangwei</groupId>
    <artifactId>demo-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>

<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>
    </dependencies>
</project>

其中spring-boot-starter-parent是springboot starter的父级依赖,统一封装了自定义starter所需的依赖和插件;

spring-boot-configuration-processor是springboot提供的工具包,用于编译期给标注了@ConfigurationProperties的配置类生成元数据信息,当在properties文件中配置相关属性时,就会根据元数据给出相应提示;

spring-boot-autoconfigure是springboot的自动装配模块,这里主要提供了自定义starter所需的注解,springboot会根据这些标记的注解完成自动装配逻辑;

lombok:非必须,其作用是帮助在编译时自动为属性生成getter/setter方法,减少代码量。

2. 定义一个配置信息实体类

package com.zhangwei;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "demo")
@Data
public class DemoProperties {
    private String name = "zhangwei";
    private String city = "beijing";
}

其中@ConfigurationProperties可以把相同前缀的配置信息映射到实体类中的属性。

3. 定义一个Service

package com.zhangwei;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;

@EnableConfigurationProperties(DemoProperties.class)
public class DemoService {

    @Autowired
    private DemoProperties demoProperties;

    public String say() {
        return "name:" + demoProperties.getName() + ",city:" + demoProperties.getCity();
    }
}

其中@EnableConfigurationProperties(xxx.class),用于开启属性配置类,并将该类加入spring容器,但是前提条件是spring能够发现DemoService类。

4. 重点:配置META-INF/spring.factories文件

在resources目录下新建META-INF/spring.factories文件,并配置:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.zhangwei.DemoService

springboot在启动时,借助@EnableAutoConfiguration中@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器,即会从classpath中搜索所有META-INF/spring.factories配置文件,并将其中org.spring-framework.boot.autoconfigure.EnableAutoConfiguration对应的配置项通过反射(Java Reflection)实例化为对应的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。自动配置的幕后英雄SpringFactoiesLoader是属于Spring框架私有的一种扩展方案(类似于Java的SPI方案java.util.ServiceLoader),其主要功能就是从指定的配置文件META-INF/spring.factories加载配置。

SPI,全称Service Provider Interface,是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。这一机制为很多框架扩展提供了可能,比如在Dubbo、JDBC中都使用到了SPI机制。

5. 测试验证

将自定义的demo-spring-boot-starter通过maven命令mvn clean install -U打成jar包,并安装在本地,在另一web项目中引入该jar包,依赖坐标如下:

<dependency>
    <groupId>com.zhangwei</groupId>
    <artifactId>demo-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

编写测试用的controller如下:

@Controller
@RequestMapping("/")
public class IndexController {

    @Autowired
    private DemoService demoService;

    @RequestMapping("/")
    @ResponseBody
    public Result index() {
        return new Result(200, demoService.say());
    }
}

配置文件如下:

demo.name=lisi
demo.city=wuhan

访问controller,如下:

点击这里复制本文地址 以上内容由goocz整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

果子教程网 © All Rights Reserved.  蜀ICP备2024111239号-5