SpringBoot Starter自定義之創(chuàng)建可復用的自動配置模塊方式
引言
Spring Boot Starter是Spring Boot生態(tài)系統(tǒng)的核心組成部分,它極大地簡化了項目的依賴管理和配置過程。通過Starter機制,開發(fā)者只需引入相應的依賴,Spring Boot就能自動完成復雜的配置工作。對于企業(yè)級應用開發(fā),我們經(jīng)常需要在多個項目中復用某些通用功能,這時創(chuàng)建自定義Starter就顯得尤為重要。
一、自定義Starter基礎知識
Spring Boot Starter本質上是一組依賴項的集合,同時結合自動配置類,為特定功能提供開箱即用的體驗。自定義Starter的核心目標是將可復用的功能模塊化,讓其他項目能夠通過簡單的依賴引入來使用這些功能。
一個標準的Spring Boot Starter通常由兩個主要組件構成:自動配置模塊和Starter模塊。自動配置模塊包含功能的具體實現(xiàn)和配置類,而Starter模塊則作為一個空殼,僅依賴于自動配置模塊和其他必要的依賴。這種分離設計使得功能實現(xiàn)與依賴管理解耦,提高了模塊的靈活性。
以下是自定義Starter的基本命名規(guī)范:
// 對于官方Starter,命名格式為: spring-boot-starter-{功能名} // 對于非官方Starter,命名格式為: {項目名}-spring-boot-starter
命名規(guī)范的遵循有助于區(qū)分官方與第三方Starter,避免潛在的命名沖突。
二、創(chuàng)建自動配置模塊
自動配置模塊是Starter的核心,它包含了功能的具體實現(xiàn)和自動配置類。
我們以創(chuàng)建一個簡單的數(shù)據(jù)加密Starter為例,展示自動配置模塊的創(chuàng)建過程。
2.1 項目結構搭建
首先創(chuàng)建一個Maven項目,命名為encryption-spring-boot-autoconfigure
,作為自動配置模塊。
項目結構如下:
encryption-spring-boot-autoconfigure/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── example/ │ │ │ └── encryption/ │ │ │ ├── autoconfigure/ │ │ │ │ └── EncryptionAutoConfiguration.java │ │ │ ├── properties/ │ │ │ │ └── EncryptionProperties.java │ │ │ └── service/ │ │ │ ├── EncryptionService.java │ │ │ └── impl/ │ │ │ └── AESEncryptionServiceImpl.java │ │ └── resources/ │ │ └── META-INF/ │ │ └── spring.factories └── pom.xml
2.2 配置屬性類
創(chuàng)建配置屬性類,用于存儲和管理加密服務的相關配置:
package com.example.encryption.properties; import org.springframework.boot.context.properties.ConfigurationProperties; /** * 加密服務配置屬性類 * 通過@ConfigurationProperties注解綁定配置文件中的屬性 */ @ConfigurationProperties(prefix = "encryption") public class EncryptionProperties { /** * 加密算法,默認為AES */ private String algorithm = "AES"; /** * 加密密鑰 */ private String key = "defaultKey123456"; /** * 是否啟用加密服務 */ private boolean enabled = true; // Getter和Setter方法 public String getAlgorithm() { return algorithm; } public void setAlgorithm(String algorithm) { this.algorithm = algorithm; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } }
2.3 服務接口及實現(xiàn)
定義加密服務接口及其實現(xiàn):
package com.example.encryption.service; /** * 加密服務接口 * 定義加密和解密的基本操作 */ public interface EncryptionService { /** * 加密字符串 * * @param content 待加密內容 * @return 加密后的內容 */ String encrypt(String content); /** * 解密字符串 * * @param encryptedContent 已加密內容 * @return 解密后的原文 */ String decrypt(String encryptedContent); }
AES加密實現(xiàn)類:
package com.example.encryption.service.impl; import com.example.encryption.properties.EncryptionProperties; import com.example.encryption.service.EncryptionService; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.util.Base64; /** * AES加密服務實現(xiàn) * 提供基于AES算法的加密和解密功能 */ public class AESEncryptionServiceImpl implements EncryptionService { private final EncryptionProperties properties; public AESEncryptionServiceImpl(EncryptionProperties properties) { this.properties = properties; } @Override public String encrypt(String content) { try { // 創(chuàng)建密鑰規(guī)范 SecretKeySpec keySpec = new SecretKeySpec( properties.getKey().getBytes(StandardCharsets.UTF_8), properties.getAlgorithm() ); // 獲取Cipher實例 Cipher cipher = Cipher.getInstance(properties.getAlgorithm()); // 初始化為加密模式 cipher.init(Cipher.ENCRYPT_MODE, keySpec); // 執(zhí)行加密 byte[] encrypted = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8)); // 返回Base64編碼后的加密結果 return Base64.getEncoder().encodeToString(encrypted); } catch (Exception e) { throw new RuntimeException("加密失敗", e); } } @Override public String decrypt(String encryptedContent) { try { // 創(chuàng)建密鑰規(guī)范 SecretKeySpec keySpec = new SecretKeySpec( properties.getKey().getBytes(StandardCharsets.UTF_8), properties.getAlgorithm() ); // 獲取Cipher實例 Cipher cipher = Cipher.getInstance(properties.getAlgorithm()); // 初始化為解密模式 cipher.init(Cipher.DECRYPT_MODE, keySpec); // 執(zhí)行解密 byte[] original = cipher.doFinal(Base64.getDecoder().decode(encryptedContent)); // 返回解密后的原文 return new String(original, StandardCharsets.UTF_8); } catch (Exception e) { throw new RuntimeException("解密失敗", e); } } }
2.4 自動配置類
創(chuàng)建自動配置類,根據(jù)條件自動裝配加密服務:
package com.example.encryption.autoconfigure; import com.example.encryption.properties.EncryptionProperties; import com.example.encryption.service.EncryptionService; import com.example.encryption.service.impl.AESEncryptionServiceImpl; 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; /** * 加密服務自動配置類 * 負責根據(jù)條件自動裝配加密服務 */ @Configuration @ConditionalOnClass(EncryptionService.class) @EnableConfigurationProperties(EncryptionProperties.class) @ConditionalOnProperty(prefix = "encryption", name = "enabled", havingValue = "true", matchIfMissing = true) public class EncryptionAutoConfiguration { /** * 注冊加密服務Bean * 當容器中不存在EncryptionService類型的Bean時,創(chuàng)建默認實現(xiàn) */ @Bean @ConditionalOnMissingBean public EncryptionService encryptionService(EncryptionProperties properties) { return new AESEncryptionServiceImpl(properties); } }
2.5 spring.factories文件
在META-INF
目錄下創(chuàng)建spring.factories
文件,指定自動配置類:
# 自動配置類 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.encryption.autoconfigure.EncryptionAutoConfiguration
2.6 Maven依賴配置
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"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>encryption-spring-boot-autoconfigure</artifactId> <version>1.0.0</version> <properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <spring-boot.version>2.7.0</spring-boot.version> </properties> <dependencies> <!-- Spring Boot AutoConfigure --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>${spring-boot.version}</version> </dependency> <!-- 用于生成配置元數(shù)據(jù) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <version>${spring-boot.version}</version> <optional>true</optional> </dependency> </dependencies> </project>
三、創(chuàng)建Starter模塊
Starter模塊是一個空殼模塊,它依賴于自動配置模塊和其他必要的依賴,向使用者提供一站式的依賴引入體驗。
3.1 項目結構
創(chuàng)建一個Maven項目,命名為encryption-spring-boot-starter
,作為Starter模塊:
encryption-spring-boot-starter/ └── pom.xml
3.2 Maven依賴配置
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"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>encryption-spring-boot-starter</artifactId> <version>1.0.0</version> <properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> <dependencies> <!-- 依賴自動配置模塊 --> <dependency> <groupId>com.example</groupId> <artifactId>encryption-spring-boot-autoconfigure</artifactId> <version>1.0.0</version> </dependency> <!-- 依賴其他必要的庫,根據(jù)功能需求添加 --> </dependencies> </project>
四、使用自定義Starter
創(chuàng)建完成后,我們可以在其他項目中使用這個自定義的Starter。
4.1 添加依賴
在項目的pom.xml
中添加依賴:
<dependency> <groupId>com.example</groupId> <artifactId>encryption-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency>
4.2 配置屬性
在application.properties
或application.yml
中配置加密服務屬性:
# 開啟加密服務 encryption.enabled=true # 設置加密算法 encryption.algorithm=AES # 設置加密密鑰 encryption.key=mySecretKey12345
4.3 使用示例
在業(yè)務代碼中注入并使用加密服務:
package com.example.demo; import com.example.encryption.service.EncryptionService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * 加密服務演示控制器 * 展示如何在業(yè)務代碼中使用自定義Starter提供的功能 */ @RestController public class EncryptionController { private final EncryptionService encryptionService; @Autowired public EncryptionController(EncryptionService encryptionService) { this.encryptionService = encryptionService; } @GetMapping("/encrypt") public String encrypt(@RequestParam String content) { return encryptionService.encrypt(content); } @GetMapping("/decrypt") public String decrypt(@RequestParam String content) { return encryptionService.decrypt(content); } }
五、Starter高級特性
5.1 條件化配置
Spring Boot提供了豐富的條件注解,用于控制Bean的裝配條件,使自定義Starter更加靈活:
// 當類路徑下存在指定類時生效 @ConditionalOnClass(name = "com.example.SomeClass") // 當Bean不存在時生效 @ConditionalOnMissingBean // 當配置屬性滿足條件時生效 @ConditionalOnProperty(prefix = "feature", name = "enabled", havingValue = "true") // 當環(huán)境為指定profile時生效 @ConditionalOnProfile("dev") // 當Web應用為Servlet類型時生效 @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
5.2 自動配置順序控制
在復雜場景下,可能需要控制多個自動配置類的執(zhí)行順序,可以使用@AutoConfigureBefore
和@AutoConfigureAfter
注解:
// 在指定自動配置類之前執(zhí)行 @AutoConfigureBefore(OtherAutoConfiguration.class) // 在指定自動配置類之后執(zhí)行 @AutoConfigureAfter(OtherAutoConfiguration.class) // 示例代碼 @Configuration @AutoConfigureAfter(DataSourceAutoConfiguration.class) public class EncryptionAutoConfiguration { // 配置代碼 }
5.3 配置元數(shù)據(jù)
為了提供更好的IDE支持,可以創(chuàng)建配置元數(shù)據(jù)文件:
{ "groups": [ { "name": "encryption", "type": "com.example.encryption.properties.EncryptionProperties", "sourceType": "com.example.encryption.properties.EncryptionProperties" } ], "properties": [ { "name": "encryption.enabled", "type": "java.lang.Boolean", "description": "是否啟用加密服務", "sourceType": "com.example.encryption.properties.EncryptionProperties", "defaultValue": true }, { "name": "encryption.algorithm", "type": "java.lang.String", "description": "加密算法", "sourceType": "com.example.encryption.properties.EncryptionProperties", "defaultValue": "AES" }, { "name": "encryption.key", "type": "java.lang.String", "description": "加密密鑰", "sourceType": "com.example.encryption.properties.EncryptionProperties", "defaultValue": "defaultKey123456" } ], "hints": [ { "name": "encryption.algorithm", "values": [ { "value": "AES", "description": "AES加密算法" }, { "value": "DES", "description": "DES加密算法" } ] } ] }
配置元數(shù)據(jù)文件應放在META-INF/spring-configuration-metadata.json
路徑下,通常由spring-boot-configuration-processor
自動生成。
總結
Spring Boot Starter是一種強大的自動配置機制,通過自定義Starter,我們可以將業(yè)務中的通用功能模塊化,實現(xiàn)代碼的高度復用。自定義Starter的核心在于合理設計自動配置類和配置屬性類,讓用戶能夠通過簡單的配置來定制功能行為。
在創(chuàng)建過程中,我們需要遵循Spring Boot的命名規(guī)范和最佳實踐,將自動配置模塊與Starter模塊分離,提高靈活性。通過條件化配置和自動配置順序控制,可以讓Starter在復雜場景中也能穩(wěn)定工作。
對于企業(yè)級應用開發(fā),自定義Starter是提升團隊效率的關鍵工具,它不僅能簡化項目配置,還能確保各個項目遵循統(tǒng)一的最佳實踐,降低維護成本。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Java使用DFA算法實現(xiàn)過濾多家公司自定義敏感字功能詳解
這篇文章主要介紹了Java使用DFA算法實現(xiàn)過濾多家公司自定義敏感字功能,結合實例形式分析了DFA算法的實現(xiàn)原理及過濾敏感字的相關操作技巧,需要的朋友可以參考下2017-08-08Spring Cloud Alibaba Nacos 入門詳解
這篇文章主要介紹了Spring Cloud Alibaba Nacos入門詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-03-03MybatisPlusException:Failed?to?process,Error?SQL異常報錯的解決辦法
這篇文章主要給大家介紹了關于MybatisPlusException:Failed?to?process,Error?SQL異常報錯的解決辦法,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2023-03-03SpringBoot+MyBatisPlus+Vue 前后端分離項目快速搭建過程(后端)
這篇文章主要介紹了SpringBoot+MyBatisPlus+Vue 前后端分離項目快速搭建過程(后端),快速生成后端代碼、封裝結果集、增刪改查、模糊查找,畢設基礎框架,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-05-05使用ScheduledThreadPoolExecutor踩過最痛的坑
這篇文章主要介紹了使用ScheduledThreadPoolExecutor踩過最痛的坑及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08