首頁  >  文章  >  Java  >  如何自訂一個starter,你學廢了麼?

如何自訂一個starter,你學廢了麼?

Java后端技术全栈
Java后端技术全栈轉載
2023-08-15 16:02:061220瀏覽

前兩天,一位朋友面試時又被問到了starter。當我在幫他做模擬面試時,我刻意強調了一下,一定要自己去動手寫一個 自訂starter,果然面試中被問到了。

如何自訂一個starter,你學廢了麼?


可能部分人沒有經歷過從Servlet到Spring MVC,如果經歷過就知道那組態是相當的繁瑣,於是後面除了個Spring Boot。

學過Spring Boot的朋友應該知道,有句話用來形容Spring Boot:約定大於設定

為什麼說Spring Boot會被稱為約定大於配置呢?

Spring Boot被稱為"約定大於配置"的原因是因為它採用了約定優於配置的設計理念。傳統的Java開發需要進行大量的配置,如XML檔案、註解等,這些配置需要開發人員自行指定。而Spring Boot則透過提供一些預設設定和約定來簡化開發流程,減少了開發人員需要手動設定的工作量。

Spring Boot透過一些預設的設定屬性和約定來自動完成一些常見的設定工作,如自動設定資料來源、自動設定Web伺服器、自動設定日誌等。開發人員只需按照約定的方式組織程式碼和設定文件,即可快速建立一個可運行的應用程式。

這種約定大於配置的設計概念使得開發人員不再需要專注於一些常規的配置細節,更專注於業務邏輯的實現。同時,Spring Boot也提供了一些可擴展的配置選項,使得開發人員可以根據自己的需求進行客製化和擴展。

總的來說,Spring Boot的約定大於配置的設計理念使得開發人員能夠更加快速、高效地開發應用程序,並且減少了配置的複雜性。這也是Spring Boot能夠成為Java開發中廣泛使用的框架之一的原因。

在面試中,問你說一下Spring Boot自動組裝原理,咱們可以簡單的這麼來回答:

Spring Boot的自動裝配原理是透過@EnableAutoConfiguration 註解和spring.factories檔案來實現的。

@EnableAutoConfiguration註解是用來開啟自動組裝的功能,該註解通常放在應用的主類別上。

spring.factories檔案是一個位於META-INF目錄下的設定文件,其中定義了各個自動組裝類別的全限定名稱。

當Spring Boot啟動時,會載入classpath下的所有spring.factories文件,並根據其中定義的自動組裝類別的全限定名,將其實例化並新增至Spring應用上下文中。

自動組裝類別通常會透過@Configuration註解來標註,同時會使用各種註解(如@ComponentScan@Import等)來實現對應的自動裝配邏輯。

透過@EnableAutoConfiguration註解和spring.factories文件,Spring Boot可以根據應用的依賴和設定訊息,自動載入和配置相應的元件,簡化了應用的配置和開發過程。

背一遍或許兩天就忘了,再背一遍也許能記得個大概。

其實,我們只要清楚如何自訂一個starter,再去回答上面的問題會輕鬆很多。

我們在使用Spring Boot開發時,最常見的就是各種starter。

常見starter

Spring Boot常用的starter有很多,以下是一些常見的starter:

  • spring-boot-starter-web:用於建立Web應用程式的starter,包括Spring MVC和Tomcat伺服器。它提供了處理HTTP請求和回應的功能。
  • spring-boot-starter-data-jpa:用於與關係型資料庫互動的starter,包括Spring Data JPA和Hibernate。它簡化了與資料庫的交互,提供了常見的CRUD操作。
  • spring-boot-starter-security:用於新增安全功能的starter,包括Spring Security和OAuth2。它提供了身份驗證、授權和安全性配置的功能。
  • spring-boot-starter-test:用於編寫單元測試和整合測試的starter,包括JUnit和Spring Test。它提供了測試框架和工具,方便進行單元測試和整合測試。
  • spring-boot-starter-actuator:用於監控和管理應用程式的starter,包括健康檢查、指標收集和遠端管理功能。它提供了監控應用程式運行狀態的功能。
  • spring-starter-cache:用於新增快取支援的starter,包括Spring Cache和Ehcache。它提供了快取資料的功能,提高應用程式的效能。
  • spring-boot-starter-data-redis:用於與Redis資料庫進行互動的starter,包括Spring Data Redis。它簡化了與Redis的交互,提供了常見的操作方法。
  • spring-boot-starter-mail:用於傳送電子郵件的starter,包括JavaMail和Spring Mail。它提供了發送電子郵件的功能。
  • spring-boot-starter-log4j2:用於使用Log4j2進行日誌記錄的starter。它提供了日誌記錄的功能,方便調試和錯誤追蹤。
  • spring-boot-starter-thymeleaf:用於使用Thymeleaf模板引擎的starter。它提供了使用Thymeleaf進行頁面渲染的功能。
  • ......

這些starter可以根據應用程式的需求選擇使用,它們提供了各種功能和便利,簡化了應用程式的開發和配置過程。

從命名上大家會發現都是以spring-boot-starter開頭的spring-boot-starter-xxx

但,我們在專案中也簡單過這樣的:mybatis-spring-boot-starter,並不是上面的那種命名方式。

其實,我們通常稱以spring-boot-starter開頭的spring-boot-starter-xxx是spring官方給咱們搞的,xxx-spring-boot-starter這種格式就是自己搞的,只是個命名而已。

我們為何不能自己也來搞個starter過過癮唄,哈哈哈,開搞。

自訂starter

我們來搞一個redisson的starter。

第一步建立一個Spring Boot項目,命名為:redisson-spring-boot-starter

其中,pom依賴重點:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.3.1.RELEASE</version>
        <!-- 不让jar进行传递 避免jar包冲突-->
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson</artifactId>
        <version>3.13.1</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

建立配置解析類別:RedissonProperties

/**
 * @author tianwc  公众号:java后端技术全栈、面试专栏
 * @version 1.0.0
 * @date 2023年07月20日 11:35
 * 在线刷题 1200+题和1000+篇干货文章:<a href="http://woaijava.cc/">博客地址</a>
 * 
 * 解析配置项
 */
@ConfigurationProperties(prefix = "tian.redisson")
public class RedissonProperties {

    private String host="localhost";
    private int port=6379;
    private int timeout;

    //get set 省略
}

自動組裝類別:RedissonAutoConfiguration

/**
 * @author tianwc  公众号:java后端技术全栈、面试专栏
 * @version 1.0.0
 * @date 2023年07月20日 11:27
 * 在线刷题 1200+题和1000+篇干货文章:<a href="http://woaijava.cc/">博客地址</a>
 */
//(条件装配)只有在我们的classpath目录下有Redisson.class 我们才自动装配RedissonClient bean
//@ConditionalOnClass(Redisson.class)
@EnableConfigurationProperties(RedissonProperties.class)
@Configuration
public class RedissonAutoConfiguration {
    private static final String PREFIX="redis://";
    @Bean
    public RedissonClient redissonClient(RedissonProperties redissonProperties){
        Config config=new Config();
        //redis单机模式
        config.useSingleServer().setAddress(PREFIX+redissonProperties.getHost()+":"+redissonProperties.getPort())
                .setConnectTimeout(redissonProperties.getTimeout());
        return Redisson.create(config);
    }
}

然後,在resources目錄下創建:META-INF目錄,在這個目錄下創建spring.factories文件,文件內容:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.tian.RedissonAutoConfiguration

完事,這麼就搞定了。是不是還沒緩過神來?

使用自訂starter

再建立個spring Boot項目,把我們自訂的starter引入進來。

<dependency>
    <groupId>com.tian</groupId>
    <artifactId>charge-sms-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

因為我們在RedissonProperties類別中對host和port賦了預設值,所以我們在application.properties檔案中,不配任何參數時就是用到的是預設值。

如果設定的話,如下:

tian.redisson.host=localhost
tian.redisson.port=6379
tian.redisson.timeout=1000

但是,你真的在​​這樣玩的時候,會發現我們平常要配置個什麼的時候,基本上都會提示的,例如:

如何自訂一個starter,你學廢了麼?

這樣提示可不就爽了嗎?

要想有这个提示,还得在redisson-spring-boot-starter中搞点事情。

相关jar上面都已经引入了这里不再赘述。

同样是在META-INF下面创建一个文件(文件名需要注意不要写错):additional-spring-configuration-metadata.json

内容如下:

{
  "properties": [
    {
      "name": "tian.redisson.host",
      "type": "java.lang.String",
      "description": "redis服务地址ip",
      "defaultValue": "localhost"
    },
    {
      "name": "tian.redisson.port",
      "type": "java.lang.Integer",
      "description": "redis服务端口号",
      "defaultValue": 6379
    },
    {
      "name": "tian.redisson.timeout",
      "type": "java.lang.Integer",
      "description": "redis连接超时时间",
      "defaultValue": 1000
    }
  ]
}

properties对应一个数组,每个配置项占一个。

  • name:就是我们的配置项
  • type:配置项类型
  • description:配置项的描述
  • defaultValue:默认值

重新打包,在使用的项目里执行Reload All Maven。

接着,再去properties文件里配置,就会有对应的提示了。

我们写一个controller来使用:

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

    @Resource
    private RedissonClient redissonClient; 

    @GetMapping("/redisson")
    public String redisson() {
        RBucket bucket = redissonClient.getBucket("name");
        if(bucket.get()==null){
            bucket.set("公众号:java后端技术全栈");
        } 
        return bucket.get().toString();
    }
}

执行结果:

如何自訂一個starter,你學廢了麼?

到这里,我们就搞定了一个自定义starter。

在实际项目中,在自定义starter时,可能还会用到下面这些注解,请注意收藏:

@Conditional:依照一定的條件進行判斷,滿足條件給容器註冊bean

@ConditionalOnMissingBean:給定的在bean不存在時,則實例化目前Bean

@ConditionalOnProperty:設定檔中符合定義的屬性則建立bean,否則不建立

@ConditionalOnBean :給定的在bean存在時,則實例化目前Bean

@ConditionalOnClass:當給定的類別名稱在類別路徑上存在,則實例化目前Bean

#@ConditionalOnMissingClass :當給定的類別名稱在類別路徑上不存在,則實例化當前Bean

上面我們只是搞了一個單機版的,其實還可以搞各種版本的主從、哨兵、cluster等,也可以搞成ssl存取方式。

自訂會了,那麼就該如何在實際專案中使用了,咱們不能老是停留在demo裡,得用到專案中才是王道。

我在充電樁專案中,發送簡訊功能中用到了自訂starter,也用到了模板方法模式。

#

以上是如何自訂一個starter,你學廢了麼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:Java后端技术全栈。如有侵權,請聯絡admin@php.cn刪除