java Spring Cloud企業快速開發架構之Spring Boot Starter的介紹及使用

畏懼小田發表於2022-01-07

Spring Boot 的便利性體現在,它簡化了很多煩瑣的配置,這對於開發人員來說是一個福音,透過引入各種 Spring Boot Starter 包可以快速搭建出一個專案的腳手架 

目前提供的 Spring Boot Starter 包有:

spring-boot-starter-web:快速構建基於 Spring MVC 的 Web 專案,使用 Tomcat 做預設嵌入式容器。 
spring-boot-starter-data-redis:操作 Redis。 
spring-boot-starter-data-mongodb:操作 Mongodb。 
spring-boot-starter-data-jpa:操作 Mysql。 
spring-boot-starter-activemq:操作 Activemq。 
……

自動配置非常方便,當我們要操作 Mongodb 的時候,只需要引入 spring-boot-starter-data-mongodb 的依賴,然後配置 Mongodb 的連結資訊 spring.data.mongodb.uri=mongodb://localhost/test 就可以使用 MongoTemplate 來運算元據,MongoTemplate 的初始化工作全部交給 Starter 來完成。

自動配置麻煩的是當出現錯誤時,排查問題的難度上升了。自動配置的邏輯都在 Spring Boot Starter 中,要想快速定位問題,就必須得了解 Spring Boot Starter 的內部原理。接下來我們自己動手來實現一個 Spring Boot Starter。

Spring Boot Starter專案建立 
建立一個專案 spring-boot-starter-demo,pom.xml 配置程式碼如下所示。

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

建立一個配置類,用於在屬性檔案中配置值,相當於 spring.data.mongo 這種形式,程式碼如下所示。

import org.springframework.boot.context.properties.ConfigurationProperties;
import lombok.Data;
@Data
@ConfigurationProperties("spring.user")
public class UserPorperties {
    private String name;
}

再定義一個 Client,相當於 MongoTemplate,裡面定一個方法,用於獲取配置中的值,程式碼如下所示。

public class UserClient {
    private UserPorperties userPorperties;
    public UserClient() {
    }
    public UserClient(UserPorperties p) {
        this.userPorperties = p;
    }
    public String getName() {
        return userPorperties.getName();
    }
}

自動建立客戶端 
一個最基本的 Starter 包定義好了,但目前肯定是不能使用 UserClient,因為我們沒有自動構建 UserClient 的例項。接下來開始構建 UserClient,程式碼如下所示。

@Configuration
@EnableConfigurationProperties(UserPorperties.class)
public class UserAutoConfigure {
    @Bean
    @ConditionalOnProperty(prefix = "spring.user", value = "enabled", havingValue = "true")
    public UserClient userClient(UserPorperties userPorperties) {
        return new UserClient(userPorperties);
    }
}

Spring Boot 會預設掃描跟啟動類平級的包,假如我們的 Starter 跟啟動類不在同一個主包下,如何能讓 UserAutoConfigure 生效?

在 resources 下建立一個 META-INF 資料夾,然後在 META-INF 資料夾中建立一個 spring.factories 檔案,檔案中指定自動配置的類: 
 

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.cxytiandi.demo.UserAutoConfigure

Spring Boot 啟動時會去讀取 spring.factories 檔案,然後根據配置啟用對應的配置類,至此一個簡單的 Starter 包就實現了。

使用 Starter 
現在可以在其他的專案中引入這個 Starter 包,程式碼如下所示。

<dependency>
    <groupId>com.cxytiandi</groupId>
    <artifactId>spring-boot-starter-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

引入之後就直接可以使用 UserClient,UserClient 在專案啟動的時候已經自動初始化好,程式碼如下所示。

@RestController
public class UserController {
    @Autowired
    private UserClient userClient;
    @GetMapping("/user/name")
    public String getUserName() {
        return userClient.getName();
    }
}

屬性檔案中配置 name 的值和開啟 UserClient:

spring.user.name=zhangsan
spring.user.enabled=true

訪問 /user/name 就可以返回我們配置的 zhangsan。

使用註解開啟 Starter 自動構建 
很多時候我們不想在引入 Starter 包時就執行初始化的邏輯,而是想要由使用者來指定是否要開啟 Starter 包的自動配置功能,比如常用的 @EnableAsync 這個註解就是用於開啟呼叫方法非同步執行的功能。

同樣地,我們也可以透過註解的方式來開啟是否自動配置,如果用註解的方式,那麼 spring.factories 就不需要編寫了,下面就來看一下怎麼定義啟用自動配置的註解,程式碼如下所示。 
 

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({UserAutoConfigure.class})
public @interface EnableUserClient {
}

這段程式碼的核心是 @Import({UserAutoConfigure.class}),透過匯入的方式實現把 UserAutoConfigure 例項加入 SpringIOC 容器中,這樣就能開啟自動配置了。

使用方式就是在啟動類上加上該註解,程式碼如下所示。

@SpringBootApplication
public class SpringBootDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemoApplication.class, args);
    }
}

使用配置開啟 Starter 自動構建 
在某些場景下,UserAutoConfigure 中會配置多個物件,對於這些物件,如果不想全部配置,或是想讓使用者指定需要開啟配置的時候再去構建物件,這個時候我們可以透過 @ConditionalOnProperty 來指定是否開啟配置的功能,程式碼如下所示。 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69994808/viewspace-2851228/,如需轉載,請註明出處,否則將追究法律責任。

相關文章