Spring Boot四大神器之創(chuàng)建自定義Starter

1. 概述

Spring Boot為開發(fā)人員提供了大多數(shù)流行的開源項(xiàng)目的啟動(dòng)器,但我們不僅限于此。

我們也可以編寫自己的自定義啟動(dòng)器。 如果想為我們的組織提供一個(gè)內(nèi)部庫,并且將它在Spring Boot上下文中使用,那么為它編寫一個(gè)啟動(dòng)器也許是一個(gè)好的習(xí)慣。

這些啟動(dòng)器使開發(fā)人員能夠避免冗長的配置并快速啟動(dòng)他們的開發(fā)。但是,由于隱藏了在后臺發(fā)生的很多事情,有時(shí)候很難理解注釋或只是在pom.xml中包含些依賴項(xiàng)就能夠?qū)崿F(xiàn)這么多功能。

在本文中,我們將揭開Spring Boot的神秘面紗,看看幕后發(fā)生了什么。然后我們將使用這些概念為我們自己的自定義庫創(chuàng)建一個(gè)啟動(dòng)器。

2. 揭開Spring Boot自動(dòng)配置的神秘面紗

2.1 自動(dòng)配置類

當(dāng)Spring Boot啟動(dòng)時(shí),它會(huì)在類路徑中查找名為spring.factories的文件。該文件位于META-INF目錄中。讓我們看一下spring-boot-autoconfigure項(xiàng)目中這個(gè)文件的片段:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration

此文件將名稱映射到Spring Boot將嘗試運(yùn)行的不同配置類。因此,根據(jù)這個(gè)片段,Spring Boot將嘗試運(yùn)行RabbitMQ,Cassandra,MongoDB和Hibernate的所有配置類。

這些類是否實(shí)際運(yùn)行將取決于類路徑上是否存在依賴類。例如,如果在類路徑中找到MongoDB的類,則將運(yùn)行MongoAutoConfiguration,并初始化所有與mongo相關(guān)的bean。

此條件初始化由@ConditionalOnClass注釋啟用。讓我們看一下MongoAutoConfiguration類的代碼片段,看看它的用法:

@Configuration
@ConditionalOnClass(MongoClient.class)
@EnableConfigurationProperties(MongoProperties.class)
@ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDbFactory")
public class MongoAutoConfiguration {
    // configuration code
}

現(xiàn)在如果MongoClient在類路徑中可用 - 這個(gè)配置類將運(yùn)行,使用默認(rèn)配置設(shè)置初始化的MongoClient來填充Spring bean工廠。

2.2 application.properties文件中的自定義屬性

Spring Boot使用一些預(yù)先配置的默認(rèn)值初始化bean。要覆蓋這些默認(rèn)值,我們通常會(huì)在application.properties文件中使用某個(gè)特定名稱聲明它們。Spring Boot容器會(huì)自動(dòng)獲取這些屬性。

讓我們看看它是如何工作的。

在MongoAutoConfiguration的代碼片段中,使用MongoProperties類聲明@EnableConfigurationProperties注釋,該類充當(dāng)自定義屬性的容器:

@ConfigurationProperties(prefix = "spring.data.mongodb")
public class MongoProperties {
 
    private String host;
 
    // other fields with standard getters and setters
}

前綴加上字段名稱可以在application.properties文件中創(chuàng)建屬性的名稱。因此,要設(shè)置MongoDB 的主機(jī),我們只需要在屬性文件中編寫以下內(nèi)容:

spring.data.mongodb.host = localhost

同樣,可以使用屬性文件設(shè)置類中其他字段的值。

3. 創(chuàng)建自定義啟動(dòng)器

根據(jù)第2節(jié)中的概念,要?jiǎng)?chuàng)建自定義啟動(dòng)器,我們需要編寫以下組件:

  • 我們庫的自動(dòng)配置類以及自定義配置的屬性類。
  • 一個(gè)啟動(dòng)程序pom,用于引入庫和autoconfigure項(xiàng)目的依賴項(xiàng)。

為了演示,我們創(chuàng)建了一個(gè)簡單的greeter庫,它將作為配置參數(shù)接收一天中不同時(shí)間的問候消息并輸出問候應(yīng)答消息。我們還將創(chuàng)建一個(gè)示例Spring Boot應(yīng)用程序來演示我們的autoconfigure和starter模塊的用法。

3.1 自動(dòng)配置模塊

我們將自動(dòng)配置模塊稱為greeter-spring-boot-autoconfigure。該模塊將有兩個(gè)主要類,即GreeterProperties - 它將通過application.properties文件和GreeterAutoConfiguartion設(shè)置自定義屬性,這將為greeter庫創(chuàng)建bean 。

讓我們看看這兩個(gè)類的代碼:

@ConfigurationProperties(prefix = "peterwanghao.samples.greeter")
public class GreeterProperties {
 
    private String userName;
    private String morningMessage;
    private String afternoonMessage;
    private String eveningMessage;
    private String nightMessage;
 
    // standard getters and setters
 
}
@Configuration
@ConditionalOnClass(Greeter.class)
@EnableConfigurationProperties(GreeterProperties.class)
public class GreeterAutoConfiguration {
 
    @Autowired
    private GreeterProperties greeterProperties;
 
    @Bean
    @ConditionalOnMissingBean
    public GreetingConfig greeterConfig() {
 
        String userName = greeterProperties.getUserName() == null
          ? System.getProperty("user.name") 
          : greeterProperties.getUserName();
         
        // ..
 
        GreetingConfig greetingConfig = new GreetingConfig();
        greetingConfig.put(USER_NAME, userName);
        // ...
        return greetingConfig;
    }
 
    @Bean
    @ConditionalOnMissingBean
    public Greeter greeter(GreetingConfig greetingConfig) {
        return new Greeter(greetingConfig);
    }
}

我們還需要在src/main/resources/META-INF目錄中添加一個(gè)spring.factories文件,其中包含以下內(nèi)容:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.peterwanghao.samples.greeter.autoconfigure.GreeterAutoConfiguration

在應(yīng)用程序啟動(dòng)時(shí),如果類路徑中存在類Greeter,則將運(yùn)行GreeterAutoConfiguration類。如果成功運(yùn)行,它將通過GreeterProperties類讀取屬性,使用GreeterConfig和Greeter bean 填充Spring應(yīng)用程序上下文。

@ConditionalOnMissingBean注釋將確保,如果他們不存在,這些bean才會(huì)創(chuàng)建。這使開發(fā)人員可以通過在其中一個(gè)@Configuration類中定義自己配置的bean來完全覆蓋自動(dòng)配置的bean 。

3.2 創(chuàng)建pom.xml

現(xiàn)在讓我們創(chuàng)建一個(gè)啟動(dòng)程序pom,它將為自動(dòng)配置模塊和greeter庫帶來依賴關(guān)系。

根據(jù)命名約定,所有不由核心Spring Boot團(tuán)隊(duì)管理的啟動(dòng)器應(yīng)該以庫名稱開頭,后面跟后綴-spring-boot-starter。所以我們將把我們的啟動(dòng)器稱為greeter-spring-boot-starter:

<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>
  <parent>
    <groupId>com.peterwanghao.samples.springboot</groupId>
    <artifactId>spring-boot-custom-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>greeter-spring-boot-starter</artifactId>
  <name>greeter-spring-boot-starter</name>
  
  <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>

        <dependency>
            <groupId>com.peterwanghao.samples.springboot</groupId>
            <artifactId>greeter-spring-boot-autoconfigure</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>com.peterwanghao.samples.springboot</groupId>
            <artifactId>greeter-library</artifactId>
            <version>${greeter.version}</version>
        </dependency>

    </dependencies>


    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <greeter.version>0.0.1-SNAPSHOT</greeter.version>
        <spring-boot.version>2.1.1.RELEASE</spring-boot.version>
    </properties>
</project>

3.3 使用Starter

讓我們創(chuàng)建一個(gè)使用啟動(dòng)器的應(yīng)用greeter-spring-boot-sample-app。在pom.xml中,我們需要將其添加為依賴項(xiàng):

<dependency>
    <groupId>com.peterwanghao.samples.springboot</groupId>
    <artifactId>greeter-spring-boot-starter</artifactId>
    <version>${greeter-starter.version}</version>
</dependency>

Spring Boot將自動(dòng)配置所有內(nèi)容,我們將準(zhǔn)備好注入和使用Greeter bean。

讓我們通過使用peterwanghao.samples.greeter前綴在application.properties文件中定義GreeterProperties的一些屬性值來改變它們的一些默認(rèn)值:

peterwanghao.samples.greeter.userName=Peter
peterwanghao.samples.greeter.afternoonMessage=Woha\Afternoon

最后,讓我們在我們的應(yīng)用程序中使用Greeter bean:

@SpringBootApplication
public class GreeterSampleApplication implements CommandLineRunner {
 
    @Autowired
    private Greeter greeter;
 
    public static void main(String[] args) {
        SpringApplication.run(GreeterSampleApplication.class, args);
    }
 
    public void run(String... args) throws Exception {
        String message = greeter.greet();
        System.out.println(message);
    }
}

4. 結(jié)論

在這個(gè)簡單教程中,我們專注于創(chuàng)建自定義Spring Boot啟動(dòng)器,以及這些啟動(dòng)器如何與自動(dòng)配置機(jī)制一起工作 - 通過后臺工作以消除大量手動(dòng)配置。

我們在本文中創(chuàng)建的完整源代碼都可以在GitHub上找到。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容