SpringBoot Starter緣起

2022-10-29 06:01:51

SpringBoot通過SpringBoot Starter零設定自動載入第三方模組,只需要引入模組的jar包不需要任何設定就可以啟用模組,遵循約定大於設定的思想。
那麼如何編寫一個SpringBoot Starter呢?我們需要考慮如下幾個問題:

  1. 如何讓SpringBoot發現我們編寫的模組?
  2. 如何讓模組讀取SpringBoot的組態檔?
  3. 如果使用者沒有在組態檔中設定必要的設定項,如何預設禁用模組?
  4. 如何讓SpringBoot知道模組有哪些設定專案,方便使用者設定組態檔?

一.模組的發現

由於SpringBoot預設的包掃描路徑是主程式所在包及其下面的所有子包裡面的元件,引入的jar包下的類是不會被掃描的。那麼如何去載入Starter的設定類呢?
SpringBoot約定會掃描Starter jar包META-INF目錄下的spring.factories檔案,只需要在spring.factories檔案裡設定要載入的類就可以了。下面的是Arthas的組態檔(arthas-spring-boot-starter-3.6.3.jar,Arthas是Alibaba開源的Java診斷工具。)。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.alibaba.arthas.spring.ArthasConfiguration,\ com.alibaba.arthas.spring.endpoints.ArthasEndPointAutoConfiguration

這樣SpringBoot在啟動的時候就會自動載入這些類存放到容器中管理。

二.模組讀取SpringBoot的組態檔

ArthasConfiguration的原始碼:

@ConditionalOnProperty(
    name = {"spring.arthas.enabled"},
    matchIfMissing = true
)
@EnableConfigurationProperties({ArthasProperties.class})
public class ArthasConfiguration {
    @ConfigurationProperties(
        prefix = "arthas"
    )
    @ConditionalOnMissingBean(
        name = {"arthasConfigMap"}
    )
    @Bean
    public HashMap<String, String> arthasConfigMap() {
        return new HashMap();
    }

    @ConditionalOnMissingBean
    @Bean
    public ArthasAgent arthasAgent(@Autowired @Qualifier("arthasConfigMap") Map<String, String> arthasConfigMap, @Autowired ArthasProperties arthasProperties) throws Throwable {
        arthasConfigMap = StringUtils.removeDashKey(arthasConfigMap);
        ArthasProperties.updateArthasConfigMapDefaultValue(arthasConfigMap);
        String appName = this.environment.getProperty("spring.application.name");
        if (arthasConfigMap.get("appName") == null && appName != null) {
            arthasConfigMap.put("appName", appName);
        }

        Map<String, String> mapWithPrefix = new HashMap(arthasConfigMap.size());
        Iterator var5 = arthasConfigMap.entrySet().iterator();

        while(var5.hasNext()) {
            Map.Entry<String, String> entry = (Map.Entry)var5.next();
            mapWithPrefix.put("arthas." + (String)entry.getKey(), entry.getValue());
        }

        ArthasAgent arthasAgent = new ArthasAgent(mapWithPrefix, arthasProperties.getHome(), arthasProperties.isSlientInit(), (Instrumentation)null);
        arthasAgent.init();
        logger.info("Arthas agent start success.");
        return arthasAgent;
    }
}
我們發現類上面兩個註解EnableConfigurationProperties和ConditionalOnProperty。這兩個註解的作用如下:
  • EnableConfigurationProperties用來指定要載入的設定類,設定類用來載入SpringBoot的組態檔,SpringBoot組態檔中可以指定Arthas的啟動引數。如果你不需要任何引數,則可以不指定EnableConfigurationProperties。
@ConfigurationProperties(
    prefix = "arthas"
)
public class ArthasProperties {
private String ip;
    private int telnetPort;
    private int httpPort;
    private String tunnelServer;
    private String agentId;
    private String appName;
    private String statUrl;
}
  • ConditionalOnProperty通過讀取SpringBoot組態檔的指定引數判斷是否啟用元件,如果判斷為False,ArthasConfiguration裡的Bean就不會被載入到容器中,即元件的開關。Arthas讀取spring.arthas.enabled來判斷是否載入元件。如果你想預設啟動,沒有開關,則可以不指定ConditionalOnProperty。

三.編寫自己的Starter

我們寫個簡單的Starter,不載入組態檔,並且預設啟動的Starter。IDE用的是是IDEA社群版。

3.1建立一個SpringBootStarter專案

3.1.1 新建專案,選擇使用Maven構建。

3.1.2 然後建立spring.factories檔案和設定類。

3.1.3 spring.factories寫入設定類的全稱。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.bjgoodwil.SpringBootStarterConfiguration

3.1.4 Maven打包

使用Maven的site命令打包jar到自己的本地倉庫中。

3.2在SpringBoot專案中引入jar

開啟一個SpringBoot專案,在pom檔案中引入Jar(直接拷貝Starter pom檔案中的引數),啟動SpringBoot專案,控制檯就會列印設定類的列印語句。

<!--自定義Starter-->
<dependency>
    <groupId>com.bjgoodwill</groupId>
    <artifactId>springbootstarter</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>