• SpringBoot如何自定义Starter?
  • 发布于 1周前
  • 45 热度
    0 评论
Spring Boot的自动配置机制为开发人员提供了一种轻松集成和配置各种功能的便捷方式。然而,随着项目的复杂性增加,更好地组织和分享通用功能变得至关重要。自定义Starter成为了理想的解决方案,旨在简化项目的依赖管理和自动配置,使开发者能够迅速而灵活地集成特定的功能模块。本文将深入探讨在Spring Boot中如何创建自定义Starter,为构建模块化且易维护的应用提供有力的支持。

接下来我们来实现一个自定义的starter。

实现自定义Starter
首先,我们需要明确自定义starter的目标功能,如提供特定领域的服务或集成第三方库。比如我们创建一个coderacademy-spring-boot-starter的starter,用于提供某些服务。例如我们的服务就实现一个打印功能:
public class CoderAcademyService {
public String sayHello(){
        return "Hello 码农Academy!";
    }
}
本文旨在介绍如何自定义starter,故而starter的功能不是本文的主要内容,后续我们会提供一个基于注解实现ES操作/搜索的服务的starter。

创建项目结构
我们创建一个名为springboot-coderacademy-starter的项目,在pom.xml中设置groupId,artifactId还有version。其中groupId与artifactId应反映starter的名称。
<groupId>com.springboot.coderacaemy</groupId>  
<artifactId>coderacermy-spring-boot-starter</artifactId>  
<version>1.0.0-SNAPSHOT</version>  
<packaging>jar</packaging>
然后我们在引入一些我们需要是用到的依赖,比如我们要使用@Configuration,@EnableConfigurationProperties等注解:
<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
    </parent>

    <groupId>com.springboot.coderacaemy</groupId>
    <artifactId>coderacermy-spring-boot-starter</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springboot-starter</name>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>
其中spring-boot-configuration-processor这个依赖主要用于IDEA支持和编译时生成元数据。本文使用的springboot版本为2.7.0

创建自动配置类
自动配置类负责定义Spring Boot应用程序中的通用配置和功能。这个类通常使用@Configuration注解进行标记,在这个类中注入服务、组件或其他你需要自动配置的对象。
import com.springboot.starter.coderacademy.service.CoderAcademyService;
import org.springframework.context.annotation.Configuration;

/**
 * @version 1.0
 * @description: <p></p >
 * @author: 码农Academy
 * @create: 2024/1/31 14:38
 */
@Configuration
public class CoderAcademyAutoConfig {

    @Bean
    public CoderAcademyService coderAcademyService(){
        return new CoderAcademyService();
    }
}
指定自动装配类
在resources文件夹下创建一个META-INF/spring.factories文件,在这个文件中指定自动装配类CoderAcademyAutoConfig:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.springboot.starter.coderacademy.config.CoderAcademyAutoConfig
在META-INF/spring.factories文件中,org.springframework.boot.autoconfigure.EnableAutoConfiguration是一个特殊的键,它的值是一个包含要应用的自动配置类的全限定名列表。当应用启动时,SpringBoot的引导过程会扫描所有已引入jar包中的spring.factories文件,并根据EnableAutoConfiguration键下的类来加载和执行相应的自动配置逻辑。

当然如果不使用这个配置,在调用方使用@ComponentScan也可以扫描到CoderAcademyAutoConfig。但是这跟Starter的设计理念相悖。在Starter的设计中,一般不推荐调用方手动进行额外的扫描。这是因为调用方引入了Starter,就应该依赖于 Starter提供的自动配置。手动扫描可能会导致不必要的麻烦,例如循环依赖、配置类的重复加载等问题。假如我们现在没有其他的配置了,比如说一下额外的属性配置,那我们就可以打包与发布了。

打包与发布
此时我们就可以将自定义Starter打包,并发布到Maven仓库或其他仓库管理工具。本地开发时,可以直接install。不必发不到私服。

测试
我们新建一个调用方的项目,在其中引入coderacademy-spring-boot-starter。
<dependency>
<groupId>com.springboot.coderacaemy</groupId>
<artifactId>coderacermy-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
我们编写测试类:
@SpringBootTest  
class SpringbootCodeApplicationTests {
private CoderAcademyService coderAcademyService;

@Test
    public void testCoderAcademy(){
       String str = coderAcademyService.sayHello();
       System.out.println(str);
    }

@Autowired
    public void setCoderAcademyService(CoderAcademyService coderAcademyService) {
        this.coderAcademyService = coderAcademyService;
    }
}
执行结果如下: