Spring Boot如何自定义自己的Starter组件?

news2024/11/25 16:43:48

一、为什么要自定义starter

在我们的日常开发工作中,经常会有一些独立于业务之外的配置模块,我们经常将其放到一个特定的 包下,然后如果另一个工程需要复用这块功能的时候,需要将代码硬拷贝到另一个工程,重新集成一 遍,麻烦至极。如果我们将这些可独立于业务代码之外的功能配置模块封装成一个个starter,复用的时 候只需要将其在pom中引用依赖即可,SpringBoot为我们完成自动装配,简直不要太爽。

二、starter的实现

虽然不同的starter实现起来各有差异,但是他们基本上都会使用到两个相同的内容:ConfigurationPropertiesAutoConfiguration。因为Spring Boot坚信“约定大于配置”这一理念,所以我们使用ConfigurationProperties来保存我们的配置,并且这些配置都可以有一个默认值,即在我们没有主动覆写原始配置的情况下,默认值就会生效,这在很多情况下是非常有用的。除此之外,starterConfigurationProperties还使得所有的配置属性被聚集到一个文件中(一般在resources目录下的application.properties),这样我们就告别了Spring项目中XML地狱。

三、命名规范

如果你快有孩子了,出生前你比较急的一定是起个名字。孩子的姓名标识着你和你爱人的血统,一定不会起隔壁老王的姓氏,肯定会招来异样的眼光。在maven中,groupId代表着姓氏,artifactId代表着名字。Spring Boot也是有一个命名的建议的。所以名字是不能够随随便便取得,可以按照官方的建议来取。

What’s in a name All official starters follow a similar naming pattern; spring-boot-starter-  , where is a particular type of application. This naming structure is intended to help when you need to find a starter. The Maven integration in many IDEs lets you search dependencies by name. For example, with the appropriate Eclipse or STS plugin installed, you can press ctrl-space in the POM editor and type “spring-boot-starter” for a complete list. As explained in the “Creating Your Own Starter” section, third party starters should not start with spring-boot, as it is reserved for official Spring Boot artifacts. Rather, a third-party starter typically starts with the name of the project. For example, a third-party starter project called thirdpartyproject would typically be named thirdpartyproject-spring-boot-starter.

大概意思:官方的 starter 的命名格式为 spring-boot-starter-{xxxx} 比如spring-boot-starter-activemq,第三方我们自己的命名格式为 {xxxx}-spring-boot-starter。比如mybatis-spring-boot-starter。如果我们忽略这种约定,是不是会显得我们写的东西不够“专业“。

四、代码工程

pom.xml

 
 
<?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">
    <parent>
        <artifactId>springboot-demo</artifactId>
        <groupId>com.et</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>


    <artifactId>xxx-spring-boot-starter</artifactId>


    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </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>

属性文件

 
 
com.person.age=23
com.person.name=Lynch
com.person.sex=F

自动配置类

 
 
package com.et.config;


import com.et.service.PersonService;
import com.et.starter.PersonProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration 
@EnableConfigurationProperties(PersonProperties.class)
@ConditionalOnClass(PersonService.class)
@ConditionalOnProperty(prefix = "com.person", value = "enabled", matchIfMissing = true)
public class PersonServiceAutoConfiguration {


    @Autowired
    private PersonProperties properties;


    // if spring container do not config bean,auto config PersonService
    @Bean
    @ConditionalOnMissingBean(PersonService.class)  
    public PersonService personService(){
        PersonService personService = new PersonService(properties);
        return personService;
    }
}

service类

 
 
package com.et.service;


import com.et.starter.PersonProperties;


public class PersonService {
    private PersonProperties properties;


    public PersonService() {
    }


    public PersonService(PersonProperties properties) {
        this.properties = properties;
    }


    public void sayHello() {
        String message = String.format("hi,my name: %s, today,I'am %s , gender: %s",
                properties.getName(), properties.getAge(), properties.getSex());
        System.out.println(message);
    }
}

PersonProperties

 
 
package com.et.starter;


import java.io.Serializable;


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


@SuppressWarnings("serial")
@ConfigurationProperties(prefix = "com.person")
public class PersonProperties implements Serializable {
    private String name;
    private int age;
    private String sex = "M";


    public PersonProperties() {


    }


    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }


    public int getAge() {
        return age;
    }


    public void setAge(int age) {
        this.age = age;
    }


    public String getSex() {
        return sex;
    }


    public void setSex(String sex) {
        this.sex = sex;
    }


}

spring.factories文件

/META-INF/spring.factories文件放在/src/main/resources目录下 注意:META-INF是自己手动创建的目录,spring.factories也是自己手动创建的文件,在该文件中配置自己的自动配置类。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.et.config.PersonServiceAutoConfiguration

项目打包

mvn clean install

代码仓库

  • https://github.com/Harries/springboot-demo

五、测试

在另外一个项目中添加starter的依赖

 
 
<dependency>
    <groupId>com.et</groupId>
    <artifactId>xxx-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

单元测试类

 
 
package com.et.starter;


import com.et.service.PersonService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;




@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {
    @Autowired
    private PersonService personService;


    @Test
    public void testHelloWorld() {
        personService.sayHello();
    }
}

运行测试类

2024-03-11 10:35:18.374 INFO 10960 --- [ main] com.et.starter.PersonServiceTest : Starting PersonServiceTest on BJDPLHHUAPC with PID 10960 (started by Dell in D:\IdeaProjects\ETFramework\xxx-spring-boot-starter-test)
2024-03-11 10:35:18.376 INFO 10960 --- [ main] com.et.starter.PersonServiceTest : No active profile set, falling back to default profiles: default
2024-03-11 10:35:19.387 INFO 10960 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2024-03-11 10:35:19.657 INFO 10960 --- [ main] com.et.starter.PersonServiceTest : Started PersonServiceTest in 1.507 seconds (JVM running for 2.188)
hi,my name: Lynch, today,I'am 23 , gender: F
2024-03-11 10:35:19.827 INFO 10960 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'

六、引用

  • https://www.cnblogs.com/linjiqin/p/13436943.html

  • http://www.liuhaihua.cn/archives/710303.html

93bac648e90847c6f9b790c3da0e8ab7.jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1511980.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SQLiteC/C++接口详细介绍之sqlite3类(三)

上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;二&#xff09; 下一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;四&#xff09; 6.sqlite3_create_module与sqlite3_create_module_v2函数 用于创建自定义SQLite模块。创建自定义模块可以让S…

ChatGPT无法登录,提示我们检测到可疑的登录行为,将阻止进一步的尝试。请与管理员联系

1. 问题描述 之前本来已经连续稳定使用ChatGPT好几个月了&#xff0c;但是今天尝试登录ChatGPT的时候&#xff0c;却提示&#xff1a;我们检测到可疑的登录行为&#xff0c;将阻止进一步的尝试。请与管理员联系。 此外&#xff0c;我还在网上看到了一些相关的消息&#xff0c;…

Kafka的基本介绍以及扩展

文章目录 基本操作新增Topic查询Topic修改Topic删除Topic 生产者和消费者创建生产者创建消费者 Broker扩展Producer扩展Topic、Partition、Message扩展存储策略容错机制 基本操作 新增Topic 指定两个分区&#xff0c;两个副本&#xff0c;replication不能大于集群中的broker数…

HarmonyOS预览功能报错:[webpack-cli] SyntaxError: Unexpected end of JSON input

harmonyos预览功能报错 在使用DevEco Studio写页面&#xff0c;进行预览的时候报错&#xff1a; [Compile Result] [webpack-cli] SyntaxError: Unexpected end of JSON input [Compile Result] at JSON.parse (<anonymous>) [Compile Result] at updateCached…

Fair Data Exchange:区块链实现的原子式公平数据交换

1. 引言 2024年斯坦福大学和a16z crypto research团队 论文 Atomic and Fair Data Exchange via Blockchain 中&#xff0c;概述了一种构建&#xff08;包含过期EIP-4844 blobs的&#xff09;fair data-markets的协议。该论文源自a16z crypto的暑期实习计划&#xff0c;与四名…

第四弹:Flutter图形渲染性能

目标&#xff1a; 1&#xff09;Flutter图形渲染性能能够媲美原生&#xff1f; 2&#xff09;Flutter性能优于React Native? 一、Flutter图形渲染原理 1.1 Flutter图形渲染原理 Flutter直接调用Skia 1&#xff09;Flutter将一帧录制成SkPicture&#xff08;skp&#xff…

2023 收入最高的十大编程语言

本期共享的是 —— 地球上目前已知超过 200 种可用的编程语言&#xff0c;了解哪些语言在 2023 为开发者提供更高的薪水至关重要。 过去一年里&#xff0c;我分析了来自地球各地超过 1000 万个开发职位空缺&#xff0c;辅助我们了解市场&#xff0c;以及人气最高和收入最高的语…

判断对象是否可以被回收:引用计数法,可达性分析,finalize()判定

引用计数法 对象每次被赋值给变量时&#xff0c;该对象的计数1&#xff0c; 若将该变量置为null,则该对象的计数-1 若该对象的计数器为0 &#xff0c;则该对象就会判定为垃圾对象 可达性分析 遍历内存中的所有变量&#xff0c;静态变量&#xff0c;然后将该变量当作GCroot根…

安装配置HBase

HBase集群需要整个集群所有节点安装的HBase版本保持一致&#xff0c;并且拥有相同的配置&#xff0c;具体配置步骤如下&#xff1a; 1. 解压缩HBase的压缩包 2. 配置HBase的环境变量 3. 修改HBase的配置文件&#xff0c;HBase的配置文件存放在HBase安装目录下的conf中 4. 首…

在没有推出硬盘的情况下,重启mac电脑,外接移动硬盘无法加载显示?

一、mac磁盘工具显示未装载 1.打开终端&#xff0c;输入 diskutil list查看当前硬盘列表&#xff0c;大多数时候&#xff0c;可以解决。 二、使用命令行装载硬盘 执行上面命令后&#xff0c;仍不起作用&#xff0c;则手动挂载&#xff0c;在命令行输入如下内容&#xff1a; …

数学建模理论与实践国防科大版

目录 1.数学建模概论 2.生活中的数学建模 2.1.行走步长问题 2.2.雨中行走问题 2.3.抽奖策略 2.4.《非诚勿扰》女生的“最优选择” 3.集体决策模型 3.1.简单多数规则 3.2.Borda数规则 3.3.群体决策模型公理和阿罗定理 1.数学建模概论 1.数学模型的概念 2.数学建模的概…

WAServiceMainContext.js:2 ReferenceError: result is not defined

WAServiceMainContext.js:2 ReferenceError: result is not defined at success (index.js? [sm]:280) at Function.forEach.u.<computed> (WASubContext.js?twechat&s1710205354985&v2.16.1:2) at :22955/appservice/<api request success callback fun…

最好用的流程编辑器bpmn-js系列之基本使用

BPMN&#xff08;Business Process Modeling Notation&#xff09;是由业务流程管理倡议组织BPMI&#xff08;The Business Process Management Initiative&#xff09;开发的一套标准的业务流程建模符号规范。其目的是为用户提供一套容易理解的标准符号&#xff0c;这些符号作…

Android audiotrack尾帧无声

前言 产品一直有用户反馈音频截断问题。在机遇巧合下现学现卖音频知识处理相关问题。 问题描述 我们查看以下简化播放器代码&#xff1a; class AACPlayer(private val filePath: String) {private val TAG "AACPlayer"private var extractor: MediaExtractor? …

nRF52832——串口 UART 和 UARTE 外设应用

nRF52832——串口 UART 和 UARTE 外设应用 UART 和 UARTE 原理UART 功能描述UARTE 功能介绍 应用实例串口打印实例串口输入与回环UART 模式串口中断 UART 和 UARTE 原理 UART 功能描述 串口 UART 也称为通用异步收发器。是各种处理器中常用的通信接口&#xff0c;在 nRF52 芯…

微信小程序实现上下手势滑动切换

效果图 思路 实现一个微信小程序的复合滚动页面&#xff0c;主要通过Swiper组件实现垂直方向的轮播功能&#xff0c;每个轮播项内部使用Scroll-View组件来展示可垂直滚动的长内容&#xff0c;如图片和文本。 代码 <!-- wxml --> <view class"swiper-container…

Spring Boot+Vue前后端分离项目如何部署到服务器

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

搜索引擎SEO策略介绍

baidu搜索&#xff1a;如何联系八爪鱼SEO baidu搜索&#xff1a;如何联系八爪鱼SEO baidu搜索&#xff1a;如何联系八爪鱼SEO 第一、 关键词的选择策略&#xff1a; 1、门户类的网站关键词选择策略&#xff1a; 网站每个页面本身基本都包含有关键词&#xff1a;网站拥有上百…

STM32-PWR电源控制

PWR(Power Control)电源控制 管理STM32内部的电源供电部分&#xff0c;可以实现可编程电压检测器和低功耗模式的功能。 电源管理器 上电复位&#xff08;POR&#xff09;和掉电复位&#xff08;PDR&#xff09; STM32内部有一个完整的上电复位(POR)和掉电复位(PDR)电路&…

免费搭建导航网站教程带免费空间域名源码

使用免费空间和免费域名免费搭建一个导航网站 手把手视频教程 https://pan.xunlei.com/s/VNsoMehs7RCjz3IClV6h2vNMA1?pwdq596#