手把手教你自定义自己SpringBoot Starter组件源码剖析

news/2024/10/21 17:34:03/

我们知道SpringBoot Starter也就是启动器。是SpringBoot组件化的一大优点。基于这个思想,基于这个思想SpringBoot 才变得非常强大,官方给我们提供很多开箱即用的启动器。

Spring Boot Starter 是 Spring Boot 的一个重要特性,它有以下优点:

  1. 依赖管理:Starter 自动处理项目的依赖关系,使得开发者无需手动添加和管理每个依赖。

  2. 自动配置:Starter 提供了一种自动配置的方式,可以根据你的 classpath 和你定义的属性自动配置 Spring 应用。

  3. 简化开发:通过提供各种服务的 Starter(如数据库、安全、缓存等),极大地简化了开发过程。

  4. 减少样板代码:由于 Starter 的自动配置和依赖管理,开发者可以专注于业务逻辑,而不是配置和基础设施代码。

  5. 快速原型开发:使用 Starter 可以快速创建可运行的原型。

  6. 易于理解和使用:Spring Boot Starter 的设计目标之一就是让非专业的开发者也能快速上手。

  7. 社区支持:除了官方提供的 Starter,还有大量的社区提供的 Starter,可以满足各种特定需求。

我现在手把手教大家如何封装自己的starter 做自己的springboot组件,当然你也可以发布自己的starter 到maven中央仓库供大家使用

剖析SpringBoot自带Starter

我们以WebMvcAutoConfiguration这个自动加载为例

自动配置类要能加载,有一个要求,源码分析结果是,需要在\META-INF\spring.factories中做如下配置

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\

这样SpringBoot在启动完成时候,会找到我们引入,的starter 找到\META-INF\spring.factories 属性文件,找到需要自动加载配置的类路径,然后帮我们自动注入到Spring IOC 容器,我们在项目中就可以直接使用了。

这里实现自动加载还要依赖一些注解如:

@Configuration // 指定这个类是个配置类
@ConditionalOnXXX // 在指定条件成立的情况下自动配置类生效
@AutoConfigureOrder //配置类顺序
@AutoConfigureAfter // 在哪个配置类之后
@Bean //给容器中添加组件@ConfigurationProperties //结合相关的XXXProperties类 来绑定相关的配置
@EnableConfigurationProperties // 让XXXProperties加入到容器中,别人就可以自动装配

自定义自己的starter

剖析了SpringBoot 官方的starter 我们自定义自己的starter,(我们仿照着写)

命名规范

配置提示

如果自定义属性文件中,需要IDEA智能提示需要引入

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

定义starter

这里我以自己封装总结我工作以来总结项目封装的一个SpringBoot starter为例

 <dependency><groupId>cn.soboys</groupId><artifactId>rest-api-spring-boot-starter</artifactId><version>1.2.0</version></dependency>

就是我自己封装的start。已经发布中央仓库。

目前更新版本1.3.0 功能如下

  1. 支持一键配置自定义RestFull API 统一格式返回
  2. 支持RestFull API 错误国际化
  3. 支持全局异常处理,全局参数验证处理
  4. 业务错误断言工具封装,遵循错误优先返回原则
  5. redis工作封装。支持所有key操作工具
  6. RestTemplate 封装 POST,GET 请求工具
  7. 日志集成。自定义日志路径,按照日志等级分类,支持压缩和文件大小分割。按时间显示
  8. 工具库集成 集成了lombok,hutool,commons-lang3,guava。不需要自己单个引入
  9. 集成mybatisPlus一键代码生成

rest-api-spring-boot-starter
仓库地址
github

  1. 自定义配置属性文件
rest-api:enabled: falselogging:path: ./logsi18n:# 若前端无header传参则返回中文信息i18n-header: Langdefault-lang: cnmessage:# admininternal_server_error:en: Internal Server Errorcn: 系统错误not_found:en: Not Foundcn: 请求资源不存在
  1. 定义属性配置类
package cn.soboys.restapispringbootstarter.i18n;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;import java.util.Map;
import java.util.Optional;/*** @author 公众号 程序员三时* @version 1.0* @date 2023/6/26 11:55* @webSite https://github.com/coder-amiao*/
//@PropertySource(value = "classpath:i18n.yaml", factory = YamlPropertySourceFactory.class)
@Configuration
@ConfigurationProperties(prefix = "rest-api.i18n")
@Data
public class I18NMessage {/*** message-key:<lang:message>*/private Map<String, Map<String, String>> message;/*** Default language setting (Default "cn").*/private String defaultLang = "cn";private String i18nHeader = "Lang";/*** get i18n message** @param key* @param language* @return*/public String message(I18NKey key, String language) {return Optional.ofNullable(message.get(key.key())).map(map -> map.get(language == null ? defaultLang : language)).orElse(key.key());}/*** get i18n message** @param key* @param language* @return*/public String message(String key, String language) {return Optional.ofNullable(message.get(key)).map(map -> map.get(language == null ? defaultLang : language)).orElse(key);}}
  1. 定义BeanAutoConfiguration自动加载配置类
package cn.soboys.restapispringbootstarter.config;import cn.soboys.restapispringbootstarter.ApplicationRunner;
import cn.soboys.restapispringbootstarter.ExceptionHandler;
import cn.soboys.restapispringbootstarter.ResultHandler;
import cn.soboys.restapispringbootstarter.aop.LimitAspect;
import cn.soboys.restapispringbootstarter.i18n.I18NMessage;
import cn.soboys.restapispringbootstarter.utils.RedisTempUtil;
import cn.soboys.restapispringbootstarter.utils.RestFulTemp;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.web.client.RestTemplate;import java.nio.charset.Charset;
import java.util.List;/*** @author 公众号 程序员三时* @version 1.0* @date 2023/6/27 11:36* @webSite https://github.com/coder-amiao*/
@Configuration
@ConditionalOnProperty(name = "rest-api.enabled", havingValue = "true")
public class BeanAutoConfiguration {@Beanpublic I18NMessage i18NMessage() {return new I18NMessage();}@Beanpublic ResultHandler resultHandler() {return new ResultHandler();}@Beanpublic ExceptionHandler exceptionHandler() {return new ExceptionHandler();}@Beanpublic StartupApplicationListener startupApplicationListener() {return new StartupApplicationListener();}@Beanpublic RestApiProperties restApiProperties() {return new RestApiProperties();}@Beanpublic RestApiProperties.LoggingProperties loggingProperties(RestApiProperties restApiProperties) {return restApiProperties.new LoggingProperties();}@Beanpublic ApplicationRunner applicationRunner() {return new ApplicationRunner();}/*** restTemplate 自动注入*/@Configuration@ConditionalOnProperty(name = "rest-api.enabled", havingValue = "true")class RestTemplateConfig {/*** 第三方请求要求的默认编码*/private final Charset thirdRequest = Charset.forName("utf-8");@Beanpublic RestTemplate restTemplate(ClientHttpRequestFactory factory) {RestTemplate restTemplate = new RestTemplate(factory);// 处理请求中文乱码问题List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();for (HttpMessageConverter<?> messageConverter : messageConverters) {if (messageConverter instanceof StringHttpMessageConverter) {((StringHttpMessageConverter) messageConverter).setDefaultCharset(thirdRequest);}if (messageConverter instanceof MappingJackson2HttpMessageConverter) {((MappingJackson2HttpMessageConverter) messageConverter).setDefaultCharset(thirdRequest);}if (messageConverter instanceof AllEncompassingFormHttpMessageConverter) {((AllEncompassingFormHttpMessageConverter) messageConverter).setCharset(thirdRequest);}}return restTemplate;}@Beanpublic ClientHttpRequestFactory simpleClientHttpRequestFactory() {SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();factory.setConnectTimeout(15000);factory.setReadTimeout(5000);return factory;}@Beanpublic RestFulTemp restFulTemp() {return new RestFulTemp();}}}
  1. 自动装配
    在项目

spring.factories 配置自己加载配置类

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.soboys.restapispringbootstarter.config.BeanAutoConfiguration,\
cn.soboys.restapispringbootstarter.config.BeanAutoConfiguration.RestTemplateConfig,\
cn.soboys.restapispringbootstarter.utils.RedisTempUtil\

扩展思考,我们可以看到SpringBoot官方stater 很多启用都类似@Enablexxx注解
这个怎么实现。我的rest-api-spring-boot-starter 1.3.0已经实现不需要在application.properties配置一行 直接在启动类或者配置类使用EnableRestFullApi就可以使用全部功能

完善文档使用可以看我

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

这篇文章

到此自己定义starter就写完了 接下来就是打包,发布到maven中央仓库

我会在 下一篇文章继续分享

留下你的思考,关注公众 程序员三时

持续输出优质内容 希望给你带来一点启发和帮助


http://www.ppmy.cn/news/763230.html

相关文章

论文笔记:Robust ECG Signal Classification for Detection of Atrial Fibrillation Using a Novel Neural Netw

6层1dcnn来识别AF&#xff08;分成四个类别&#xff09;&#xff0c;使用skip connection残差网络来加速计算。 实验数据&#xff1a; 16层1D残差卷积神经网络&#xff1a;

HGDB过期时的提示

2019-09-13 07:28:42.076 HKT [38100] LOG: 00000: Warning: This is a trial license, it has expired, database will shut down. Please replace with a official license then try to restart database.

PLSQL Developer 试用版30天试用期到了的解决办法

PLSQL Developer 试用版有30天限制&#xff0c;到了限制时间后&#xff0c;将如下注册表删除&#xff0c;就可以继续使用30天&#xff01; HKEY_CURRENT_USER\Software\Allround Automations HKEY_CURRENT_USER\Software\Microsoft\Security 本文转自shangshanyang51CTO博客&…

论文笔记:Automated Detection of Arrhythmias Using Different Intervals of Tachycardia ECG Segments with C

Automated Detection of Arrhythmias Using Different Intervals of Tachycardia ECG Segments with Convolutional Neural Network 主要是用cnn来识别不同种类的心律失常 名词解释 atrial fibrillation&#xff1a;心房颤动&#xff08;简称房颤&#xff09;是最常见的持续性…

【论文阅读笔记】Automated detection of atrial fibrillation and atrial flutter in ECG signals based on convol

论文阅读&#xff1a;Automated detection of atrial fibrillation and atrial flutter in ECG signals based on convolutional 一、摘要 文章针对房颤&#xff08;AF&#xff09;和房扑&#xff08;AFL&#xff09;两种易混淆的两种心律失常类型&#xff0c;提出了一种由CNN…

USC ECG Learning Center/ ECG Glossary

ECG Glossary -----------------ECG 术语 Click to jump directly to one of the following categories: ----------------点击链接直接跳至某一类型&#xff1a; Features of Normal ECGs ----------------正常ECG特征 Atrial R…

软件测试基础知识面试题目(25题英文题目)

软件测试基础知识面试题目&#xff08;25题英文题目&#xff09; 1. Verification is: a. Checking that we are building the right system b. Checking that we are building the system right c. Performed by an independent test team d. Making sure that it is what th…

搭建帮助中心5大注意事项

在现代互联网时代&#xff0c;为企业网站建立一个优雅实用的网站帮助中心变得尤为重要。一个好的网站帮助中心可以帮助企业解决客户的难点、痛点&#xff0c;提高客户满意度、期待值&#xff0c;从而更好地留住客户&#xff0c;增加收入。 如果没有帮助中心或者是帮助中心创建…