乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Spring Boot自定義starter必知必會(huì)條件

       新進(jìn)小設(shè)計(jì) 2021-06-17

      前言

      在目前的Spring Boot框架中,不管是Spring Boot官方還是非官方,都提供了非常多的starter系列組件,助力開(kāi)發(fā)者在企業(yè)應(yīng)用中的開(kāi)發(fā),提升研發(fā)人員的工作效率,Spring Boot框架提出的約定大于配置的規(guī)則,確實(shí)幫助開(kāi)發(fā)者簡(jiǎn)化了以前Spring MVC時(shí)代的很多繁雜的配置。讓開(kāi)發(fā)者用起來(lái)也是非常爽的。

      盡管Spring Boot或者一些開(kāi)源組件已經(jīng)幫助我們提供了非常多的starter組件,在滿(mǎn)足日常的開(kāi)發(fā)中,已經(jīng)完全沒(méi)有問(wèn)題了。但有時(shí)候因?yàn)樾枨蟮目勺冃?,?dǎo)致企業(yè)架構(gòu)也會(huì)隨著調(diào)整,那么在Spring Boot框架中,官方或開(kāi)源的第三方starter肯定不能滿(mǎn)足企業(yè)內(nèi)部研發(fā)人員的要求,這時(shí)候就需要開(kāi)發(fā)者自定義企業(yè)內(nèi)部的starter了。

      企業(yè)或個(gè)人自定義Spring Boot的starter組件主要從哪些方面來(lái)入手呢,或者什么時(shí)候需要自定義starter組件?我個(gè)人認(rèn)為主要有以下幾個(gè)方面:

      • 規(guī)范企業(yè)內(nèi)部編碼流程,統(tǒng)一各個(gè)技術(shù)中間件的代碼規(guī)范
      • 減少不同類(lèi)型中間件的使用成本,提升研發(fā)人員的研發(fā)工作效率
      • 減少冗余代碼的使用,統(tǒng)一封裝,統(tǒng)一管理。
      • 屏蔽中間件底層細(xì)節(jié),暴露配置屬性及方法,減少學(xué)習(xí)使用成本
      • 可能還有更多?

      本篇博客結(jié)合自身的開(kāi)發(fā)經(jīng)驗(yàn)以及目前Spring Boot如何配置元數(shù)據(jù)的官方介紹文檔進(jìn)行結(jié)合,進(jìn)行綜合闡述。

      Spring Boot官方元數(shù)據(jù)文檔地址:https://docs./spring-boot/docs/current/reference/html/appendix-configuration-metadata.html

      封裝Spring Boot的starter范圍可以是一組規(guī)范的業(yè)務(wù)方法,也可以是通用的中間件底層。開(kāi)發(fā)者通過(guò)封裝,一定程度上也能起到規(guī)范企業(yè)編碼的作用,同時(shí)也能組合復(fù)用公共業(yè)務(wù)邏輯。

      那么我們?cè)谧远xSpring Boot框架的starter組件時(shí),我們需要準(zhǔn)備什么呢?

      我認(rèn)為主要包含以下幾個(gè)方面:

      • 自定義starter的作用
      • 命名規(guī)范
      • 理解Maven或者Gradle依賴(lài)包管理的jar包引用傳遞機(jī)制
      • 理解Spring Boot框架中基于Java代碼的Configuration配置
      • 理解Spring Boot框架自動(dòng)裝載的過(guò)程
      • 學(xué)會(huì)利用Spring Boot提供的@Conditional系列條件注入充分發(fā)揮Spring Boot的優(yōu)點(diǎn)
      • 學(xué)會(huì)如何配置自定義starter組件時(shí)對(duì)外的屬性注釋配置,可以參考官方文檔

      自定義starter的作用

      我們?cè)谧远xstarter組件之前,開(kāi)發(fā)者首先需要想清楚,這個(gè)starter組件能帶來(lái)什么,簡(jiǎn)化開(kāi)發(fā)?或者復(fù)用組件的封裝供其他同事使用,不寫(xiě)重復(fù)代碼等等,這些都是需要思考清楚的。

      自定義starter的場(chǎng)景很多,例如:

      • 項(xiàng)目中發(fā)送短信對(duì)接了不同的云服務(wù)商,那么可以封裝一個(gè)短信的starter,屏蔽對(duì)接的細(xì)節(jié),開(kāi)發(fā)者只需要配置相應(yīng)的廠商配置信息就可以使用該服務(wù)商發(fā)送短信了
      • OSS存儲(chǔ)對(duì)接不同的云服務(wù)商,例如阿里云、七牛云、騰訊云等等
      • 企業(yè)內(nèi)部中間件封裝使用,簡(jiǎn)化開(kāi)發(fā)配置
      • more...

      根據(jù)筆者的經(jīng)驗(yàn),我認(rèn)為自定義的starter的作用無(wú)外乎以下幾個(gè)方面:

      • 充分利用Spring的特性,容器/依賴(lài)注入特性,將核心的類(lèi)組件注入容器中,方便開(kāi)發(fā)者通過(guò)注入直接獲取拿來(lái)使用
      • 通過(guò)屬性初始化中間件的流程,屏蔽具體的細(xì)節(jié)
      • ....

      starter命名規(guī)范

      根據(jù)Spring Boot的官方要求,如果是開(kāi)發(fā)者指定第三方的starter組件,那么命名規(guī)范是yourname-spring-boot-starter

      Knife4j舉例說(shuō)明如下:

      <dependency>
          <groupId>com.github.xiaoymin</groupId>
          <artifactId>knife4j-spring-boot-starter</artifactId>
          <!--在引用時(shí)請(qǐng)?jiān)趍aven中央倉(cāng)庫(kù)搜索2.X最新版本號(hào)-->
          <version>2.0.8</version>
      </dependency>
      

      而Spring Boot官方維護(hù)發(fā)布的starter名稱(chēng)規(guī)范則是:spring-boot-starter-name

      例如我們引用最多的web組件,引用maven配置如下:

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      

      jar包引用傳遞依賴(lài)機(jī)制

      這是自定義封裝Spring Boot的starter的前提條件,Gradle筆者并未使用過(guò),這里僅以Maven為例進(jìn)行闡述說(shuō)明!

      通常我們?cè)诜庋b一個(gè)SDK的jar包時(shí),該jar包可能需要引用到第三方的jar包作為依賴(lài)包來(lái)輔助我們完成對(duì)該jar包的封裝,但是我們?cè)谝玫臅r(shí)候是有講究的。

      針對(duì)Spring Boot的自定義starter說(shuō)到底也是一個(gè)jar包,既然是jar包必然會(huì)用到第三方的jar(ps:全部都是你寫(xiě)的代碼除外),那么我們應(yīng)該如何明確在starter中的jar包的依賴(lài)傳遞,我認(rèn)為主要有以下方面:

      • 作為第三方組件使用jar包時(shí),明確第三方組件的版本
      • 作為編譯期間的包,需要修改默認(rèn)的scope范圍值,僅僅在編譯期間生效,最終打包后引用不傳遞
      • 自定義封裝starter必須引用Spring Boot官方提供的

      在定義Spring Boot的第三方starter時(shí),主要用到Maven管理jar包中的兩種依賴(lài)隔離方式(均可以使用),分別如下:

      • 明確使用<optional>true></optional>屬性來(lái)強(qiáng)指定jar包不傳遞
      • 使用<scope>provided</scope>僅僅在編譯期間有效,jar包依賴(lài)性不傳遞

      一般我們?cè)谧远xSpring Boot的starter組件時(shí),都需要引用Spring Boot提供給開(kāi)發(fā)者的依賴(lài)包,如下:

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-autoconfigure</artifactId>
          <version>2.3.0.RELEASE</version>
          <scope>provided</scope>
      </dependency>
      

      當(dāng)然,你也可以使用optional模式,如下:

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-autoconfigure</artifactId>
           <version>2.3.0.RELEASE</version>
           <optional>true</optional>
      </dependency>
      

      Java代碼方式的Configuration

      基于Java編碼的方式配置Spring的Bean已經(jīng)成了目前的主流,這主要也是得益于Spring Boot框架的流行!

      在Spring MVC框架流行的時(shí)候,開(kāi)發(fā)人員一般都是通過(guò)配置XML文件來(lái)注入實(shí)體Bean的

      而通過(guò)java編碼的方式注入Bean的前提是@Configuration注解加在一個(gè)配置Java實(shí)體類(lèi)上即可,示例如下:

      @Configuration
      public class MyAutoConfiguration{
          
          //do others...
          
      }
      

      Spring Boot框架的自動(dòng)裝載

      對(duì)于Spring Boot框架自定義的starter組件來(lái)說(shuō),提供的使用方式而言,我認(rèn)為目前主要有3種方式,這個(gè)主要看封裝starter組件的作者如何開(kāi)放來(lái)定

      手工@Import導(dǎo)入

      第一種情況:使用者使用@Import注解將封裝的starter組件的Java編碼Configuration配置文件進(jìn)行導(dǎo)入

      假設(shè)目前封裝的一個(gè)簡(jiǎn)單的Configuration配置如下:

      @Configuration
      public class DemoAuthConfiguration {
      
          @Bean
          public DemoClient demoClient(){
              return new DemoClient();
          }
      
      }
      

      開(kāi)發(fā)者通過(guò)DemoAutoConfiguration.java向Spring的容器中注入了一個(gè)DemoClient的實(shí)體Bean,由于隸屬于不同的package包路徑,自定義的starter組件包路徑是:com.demo.spring

      而開(kāi)發(fā)者的項(xiàng)目主目錄包路徑是:com.test,所以Spring Boot框架默認(rèn)是不會(huì)加載該配置的,此時(shí),如果開(kāi)發(fā)者要在Spring的容器中獲取DemoClient的實(shí)體Bean應(yīng)該怎么辦呢?使用者應(yīng)該在自己的主配置中使用@Import注解將該配置導(dǎo)入進(jìn)來(lái)交給Spring容器初始化時(shí)進(jìn)行創(chuàng)建,示例如下:

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

      提供便于記憶的注解@EnableXXX

      @Enablexxx系列注解相信開(kāi)發(fā)者并不陌生,比如我們要使用Spring Boot的定時(shí)任務(wù)功能,我們會(huì)在啟動(dòng)入口引入@EnableScheduling注解,我們使用Springfox的Swagger組件,我們會(huì)引入@EnableSwagger2注解

      其實(shí)這種方式只是為了讓開(kāi)發(fā)者能夠更加方便的記憶,一個(gè)@Enablexxx系列注解,其所代表的功能特點(diǎn)也基本符合該starter組件,是在上面手工通過(guò)@Import注解的升級(jí)版本。

      畢竟Enable單詞所代表的含義是啟用,這有利于開(kāi)發(fā)者記憶

      繼續(xù)通過(guò)上面第一種的示例進(jìn)行改在,此時(shí),我們可以提供@EnableDemoClient注解,代碼示例如下:

      @Documented
      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.TYPE)
      @Import(DemoAutoConfiguration.class)
      public @interface EnableDemoClient {
      
      }
      

      大家應(yīng)該也看到了,我們?cè)谠?code>@EnableDemoClient注解中,使用了@Import注解的方式導(dǎo)入了DemoAutoConfiguration配置

      此時(shí),我們?cè)陧?xiàng)目中可以使用@EnableDemoClient注解了,代碼示例如下:

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

      當(dāng)然,@Enable這種注解作用不僅僅局限于此,還可以在該注解上定義外部的配置屬性,通過(guò)配置該注解的方式達(dá)到最終初始化的目的。

      自動(dòng)裝載

      自動(dòng)裝載是Spring Boot的一重大特點(diǎn),開(kāi)發(fā)者通過(guò)配置文件的方式即可默認(rèn)加載第三方的starter配置,非常的方便,是上面兩種方式的升級(jí)版

      在之前的基礎(chǔ)上,如果開(kāi)發(fā)者希望在Maven的pom.xml工程中引入了該組件,就可以使用DemoClient類(lèi),那么此時(shí)我們應(yīng)該怎么做呢?

      我們需要在工程中創(chuàng)建spring.factories文件,文件目錄:src/resources/META-INF/spring.factories

      spring.factories文件中,配置開(kāi)發(fā)者自定義的configuration類(lèi),如下:

      org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.demo.spring.DemoAutoConfiguration
      

      配置好后,此時(shí)再打包我們自定義的starter組件,Spring Boot框架默認(rèn)會(huì)自動(dòng)裝載該配置類(lèi),我們?cè)跇I(yè)務(wù)代碼中也就可以直接使用了

      我們可以在SpringApplication.java源碼中看到Spring Boot初始化獲取該類(lèi)列表的過(guò)程

      private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
      ClassLoader classLoader = getClassLoader();
      // Use names and ensure unique to protect against duplicates
      Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
      List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
      AnnotationAwareOrderComparator.sort(instances);
      return instances;
      }
      

      上述方法中的SpringFactoriesLoader.loadFactoryNames方法如下:

      public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
      String factoryTypeName = factoryType.getName();
      return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
      }
      
      private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
          MultiValueMap<String, String> result = cache.get(classLoader);
          if (result != null) {
              return result;
          }
      
          try {
              //加載META-INF/spring.factories配置,創(chuàng)建MultiValueMap集合放到該集合中
              Enumeration<URL> urls = (classLoader != null ?
                                       classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                                       ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
              result = new LinkedMultiValueMap<>();
              while (urls.hasMoreElements()) {
                  URL url = urls.nextElement();
                  UrlResource resource = new UrlResource(url);
                  Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                  for (Map.Entry<?, ?> entry : properties.entrySet()) {
                      String factoryTypeName = ((String) entry.getKey()).trim();
                      for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
                          result.add(factoryTypeName, factoryImplementationName.trim());
                      }
                  }
              }
              cache.put(classLoader, result);
              return result;
          }
          catch (IOException ex) {
              throw new IllegalArgumentException("Unable to load factories from location [" +
                                                 FACTORIES_RESOURCE_LOCATION + "]", ex);
          }
      }
      

      充分利用Spring Boot提供的@Conditional條件注入組件

      通過(guò)上面的文章介紹,為Spring Boot框架制定一個(gè)簡(jiǎn)單的starter組件相信已經(jīng)不在話(huà)下。但是,這才僅僅開(kāi)始而已。

      在上面介紹的自動(dòng)裝載過(guò)程中,開(kāi)發(fā)者是否會(huì)存在疑問(wèn)?

      當(dāng)我們?cè)趐om.xml引入我們自定義的starter組件后,Spring Boot框架默認(rèn)會(huì)將該組件直接注入到Spring的容器中,這種方式雖然在使用上并沒(méi)有什么問(wèn)題,但當(dāng)我們封裝給第三方使用時(shí),這種方式往往會(huì)存在沖突,假設(shè)開(kāi)發(fā)者自定義的starter組件中包含了向容器中注入Filter等過(guò)濾器,那么該過(guò)濾器直接生效,會(huì)全范圍影響整個(gè)應(yīng)用程序.這在實(shí)際開(kāi)發(fā)中是不允許的!

      那么應(yīng)該怎么辦呢?此時(shí),我們就需要充分利用Spring Boot框架為開(kāi)發(fā)者提供的@Conditional系列條件注入了

      條件注入顧名思義,就是只有使用者滿(mǎn)足了組件規(guī)定的條件時(shí),組件才會(huì)向Spring容器中進(jìn)行注入Bean或者初始化的操作.這種方式也是將選擇權(quán)直接交給使用者進(jìn)行選擇,減少非必要的組件沖突,是在Spring Boot自定義starter組件中必不可少的一環(huán)。

      條件注入通常也配合屬性類(lèi)一起來(lái)進(jìn)行使用,提供配置屬性選項(xiàng)也是方便使用者在Spring Boot的配置文件application.yml或者application.properties進(jìn)行配置開(kāi)啟操作,例如我們常見(jiàn)的配置操作如下:

      server:
        port: 18568
        servlet:
          context-path: /test
      

      為Spring Boot的程序指定啟動(dòng)端口號(hào)和context-path屬性.

      我們繼續(xù)以上面示例中的DemoClient為例進(jìn)行闡述

      假設(shè)我們的DemoClient是對(duì)接外部API接口的封裝組件,該組件規(guī)定訪問(wèn)外部API時(shí)需要提供appidsecret,根據(jù)appid及secret獲取token,最后根據(jù)token才能調(diào)用API獲取接口數(shù)據(jù),

      那么,此時(shí),我們的DemoClient的部分模擬接口代碼可能會(huì)如下面示例:

      public class DemoClient {
          private final String appid;
          private final String secret;
      
          public DemoClient(String appid, String secret) {
              this.appid = appid;
              this.secret = secret;
          }
      
          /**
           * 獲取資源
           * @return
           */
          public String listResources(){
              //獲取token
              String token=getToken();
              //根據(jù)Token請(qǐng)求數(shù)據(jù)
              return UUID.randomUUID().toString();
          }
      
          private String getToken() {
              //根據(jù)appid & secret獲取第三方API接口token
              return null;
          }
      }
      
      

      在上面的代碼示例中,如果開(kāi)發(fā)者要使用DemoClient的方法調(diào)用第三方的接口資源,那么需要傳遞appidsecret參數(shù)才能構(gòu)造實(shí)體類(lèi),又考慮到我們需要利用Spring Boot的條件注入,只有開(kāi)發(fā)者配置了開(kāi)啟操作,才能在Spring容器中使用DemoClient的方法。

      那么此時(shí),我們可以給該starter組件抽象一個(gè)DemoProperties的外部配置類(lèi)來(lái)交給使用者在配置文件中進(jìn)行配置開(kāi)啟操作,代碼示例如下:

      @ConfigurationProperties(prefix = "demo")
      public class DemoProperties {
          /**
           * 是否啟用
           */
          private boolean enable=false;
          
          private String appid;
          private String secret;
          
          //getter and setter...
      }
      

      在配置類(lèi)屬性中,我們使用到了@ConfigurationProperties注解,并配置了prefix前綴參數(shù),配置前綴也是自定義starter組件中所必須的,這約束了命名空間。一般是結(jié)合自身的業(yè)務(wù)以及starter組件所代表的功能含義進(jìn)行命名prefix,有助于開(kāi)發(fā)使用者記憶。

      此時(shí),我們的DemoAutoConfiguration.java配置類(lèi)進(jìn)行了調(diào)整,代碼如下:

      @Configuration
      @EnableConfigurationProperties(DemoProperties.class)
      @ConditionalOnProperty(name = "demo.enable",havingValue = "true")
      public class DemoAutoConfiguration {
      
          @Bean
          public DemoClient demoClient(DemoProperties demoProperties){
              return new DemoClient(demoProperties.getAppid(), demoProperties.getSecret());
          }
      
      }
      

      和上面的配置類(lèi)進(jìn)行比較不難發(fā)現(xiàn),此處我們又多用了兩個(gè)注解:

      • @EnableConfigurationProperties:該注解是我們自定義指定Proerpty實(shí)體類(lèi)時(shí),必須啟用的注解,和實(shí)體類(lèi)中的@ConfigurationProperties注解配合一起使用
      • @ConditionalOnProperty:Spring Boot框架中條件注入的一種,代碼根據(jù)配置的屬性進(jìn)行條件判斷注入,此處我們配置了只有當(dāng)demo.enable=true時(shí),DemoAutoConfiguration配置類(lèi)才會(huì)加載,向Spring容器中注入DemoClient的實(shí)體Bean

      當(dāng)自定義starter組件封裝到這一步時(shí),基本已經(jīng)快完結(jié)了,開(kāi)發(fā)者可以通過(guò)在Spring Boot的配置文件中進(jìn)行配置,來(lái)開(kāi)啟是否使用DemoClient組件

      demo:
        # 通過(guò)配置該屬性的true 或者false ,來(lái)開(kāi)啟組件的使用
        enable: true
        appid: xxx
        secret: xxxx
      

      屬性元數(shù)據(jù)配置

      通過(guò)上面的配置,我們已經(jīng)能夠自定義一個(gè)Spring Boot框架的starter組件了,但是對(duì)于使用者來(lái)說(shuō),封裝該starter組件的開(kāi)發(fā)者還尚有最后一步需要完成,那就是給屬性類(lèi)提供元數(shù)據(jù)注釋?zhuān)峁┰獢?shù)據(jù)注釋也是為了讓使用者在配置application.yml屬性時(shí),通過(guò)IDEA等編輯器能夠給出提示,這對(duì)使用者而已是大有裨益的,因?yàn)槊恳粋€(gè)屬性都會(huì)有相應(yīng)的注釋供開(kāi)發(fā)者進(jìn)行參考。例如Knife4j組件提供的元數(shù)據(jù)注釋如下圖:

      那么我們?cè)谥贫╯tarter組件時(shí),如何給屬性類(lèi)提供元數(shù)據(jù)注釋呢?目前主要有兩種方式:

      引入spring-boot-configuration-processor自動(dòng)注釋

      我們可以在自定義是starter組件中引入該組件,依賴(lài)如下:

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-configuration-processor</artifactId>
          <version>2.3.0.RELEASE</version>
          <optional>true</optional>
      </dependency>
      

      引入該組件后,此時(shí),我們只需要在我們的Java屬性類(lèi)中給每一個(gè)屬性使用標(biāo)準(zhǔn)的javadoc進(jìn)行注釋即可,如下:

      @ConfigurationProperties(prefix = "demo")
      public class DemoProperties {
          /**
           * 是否啟用
           */
          private boolean enable=false;
      
          /**
           * 第三方appid
           */
          private String appid;
          /**
           * 第三方secret
           */
          private String secret;
          
          //getter and setter...
      }
      

      最終在使用時(shí),就會(huì)出現(xiàn)提示,如下圖:

      這種方式如果屬性類(lèi)不是太多的情況下,開(kāi)發(fā)者可以使用,很方便

      手工編寫(xiě)spring-configuration-meatadata.json文件

      spring-boot-configuration-processor組件最終在打包生成starter的jar包時(shí),也是幫助我們自動(dòng)生成了spring-configuration-metadata.json文件,該文件和上面提到的spring.factories是同級(jí)目錄

      手工編寫(xiě)spring-configuration-metadata.json也是我推薦的方式,因?yàn)椴粌H僅是每個(gè)屬性的注釋?zhuān)袝r(shí)候我們還可以用更多的屬性配置以便使用者使用。

      結(jié)果如下:

      {
        "groups": [
          {
            "name": "demo",
            "type": "com.demo.spring.DemoProperties",
            "sourceType": "com.demo.spring.DemoProperties"
          }
        ],
        "properties": [
          {
            "name": "demo.appid",
            "type": "java.lang.String",
            "description": "第三方appid",
            "sourceType": "com.demo.spring.DemoProperties"
          },
          {
            "name": "demo.enable",
            "type": "java.lang.Boolean",
            "description": "是否啟用",
            "sourceType": "com.demo.spring.DemoProperties",
            "defaultValue": false
          },
          {
            "name": "demo.secret",
            "type": "java.lang.String",
            "description": "第三方secret",
            "sourceType": "com.demo.spring.DemoProperties"
          }
        ],
        "hints": []
      }
      

      我們主要使用到的屬性有3個(gè):groups、properties、hints

      groups

      字面意思分組,按我的理解即當(dāng)我們使用的實(shí)體時(shí),配置的prefix即代表該group,例如上面我們?yōu)?code>DemoProperties配置了prefix的前綴是demo,那么分組這里可以設(shè)置為demo,當(dāng)然如果DemoProperties類(lèi)中包含的屬性是一個(gè)第三方類(lèi),假設(shè)如下:

      public class DemoProperties{
          
          private OtherProperties other;
      }
      

      那么我們可以在groups屬性中配置一個(gè)名為demo.other的分組名稱(chēng)

      其包含的屬性如下:

      屬性名稱(chēng) 類(lèi)型 說(shuō)明
      name String 分組名稱(chēng),可以理解為prefix
      type String 組數(shù)據(jù)類(lèi)名
      description String 分組簡(jiǎn)單的描述,可以省略
      sourceType String 組數(shù)據(jù)源類(lèi)名,同type,如果源類(lèi)型未知,可以忽略該屬性
      sourceMethod String 組方法的名稱(chēng),(例如,帶@ConfigurationProperties注解的@Bean方法的名稱(chēng))。 如果源方法未知,則可以省略。

      properties

      顧名思義,就是我們實(shí)體類(lèi)每個(gè)屬性的配置,有多少屬性需要添加元數(shù)據(jù)注釋說(shuō)明,就需要在該數(shù)組下全部添加,需要注意的是配置name時(shí)需要配置全路徑,例如:demo.enable

      其包含的屬性如下:

      屬性名稱(chēng) 類(lèi)型 說(shuō)明
      name String 屬性名稱(chēng)
      type String 屬性類(lèi)型
      description String 屬性的簡(jiǎn)介說(shuō)明
      sourceType String 該屬性歸屬于那個(gè)類(lèi)型
      defaultValue Object 該屬性默認(rèn)值
      deprecation Deprecation 用于指定該屬性是否過(guò)時(shí)

      過(guò)時(shí)選項(xiàng)Deprecation包含以下幾個(gè)屬性:

      名稱(chēng) 類(lèi)型 說(shuō)明
      level String 過(guò)時(shí)的級(jí)別,可以指定warning或者error,當(dāng)指定為warning時(shí),代表該屬性還可用,而指定error則代表徹底廢棄
      reason String 原因
      replacement String 替換屬性

      hints

      針對(duì)該屬性,我的理解是類(lèi)似于Java中的枚舉,只不過(guò)是給每一個(gè)屬性的值配置一個(gè)說(shuō)明,方便使用者在配置的時(shí)候能夠按照規(guī)定的值進(jìn)行正確配置

      例如上面我們的示例:demo.enable屬性,該屬性類(lèi)型為Boolean類(lèi)型,要配置也只有兩種值(true或者false)

      那么我們可以給該值配置一個(gè)hints進(jìn)行說(shuō)明,示例如下:

      "hints": [
          {
            "name": "demo.enable",
            "values":[
              {
                "value": true,
                "description": "啟用DemoClient組件"
              },
              {
                "value": false,
                "description": "禁用DemoClient組件"
              }
            ]
          }
      ]
      

      當(dāng)我們進(jìn)行這樣的配置后,最終使用者在使用時(shí)就會(huì)出現(xiàn)如下圖所示的提示:

      這對(duì)使用該starter組件的開(kāi)發(fā)者來(lái)說(shuō),每個(gè)屬性都有相應(yīng)的說(shuō)明,是非常方便的

      hints主要包含的屬性如下:

      名稱(chēng) 類(lèi)型 說(shuō)明
      name String 屬性名稱(chēng)
      values ValueHint[] 一個(gè)ValueHint的數(shù)組
      providers ValueProvider[] 一個(gè)ValueProvinder數(shù)組

      ValueHint是對(duì)其提供的值進(jìn)行注釋說(shuō)明,其屬性如下:

      名稱(chēng) 類(lèi)型 說(shuō)明
      value Object 屬性對(duì)應(yīng)的值
      description String 該值的描述信息

      ValueProvider包含屬性:

      名稱(chēng) 類(lèi)型 說(shuō)明
      name String 屬性名稱(chēng)
      parameters JSON Object 提供程序支持的其他參數(shù)類(lèi)型

      在上面我提過(guò),hints類(lèi)似于枚舉,這映射到ValueHint屬性,當(dāng)我們配置了hints屬性中的values時(shí)而不提供providers屬性時(shí),如果開(kāi)發(fā)者最終在使用時(shí),只能配置ValueHint中定義的值,否則配置其他值時(shí)會(huì)在IDEA編輯器中就會(huì)爆紅出錯(cuò)

      還是以上面的示例,假設(shè)我們給appid配置hint值,如下:

      "hints": [
          {
            "name": "demo.appid",
            "values":[
              {
                "value": "test1",
                "description": "測(cè)試appid1"
              },
              {
                "value": "test2",
                "description": "測(cè)試appid2"
              }
            ]
          }
      ]
      

      那么我們?cè)谑褂媒M件時(shí),在application.yml配置文件中配置其他值時(shí),idea會(huì)提示錯(cuò)誤,如下圖:

      此時(shí),providers屬性就可以排上用場(chǎng)了

      修改上面的配置如下:

      "hints": [
          {
            "name": "demo.appid",
            "values":[
              {
                "value": "test1",
                "description": "測(cè)試appid1"
              },
              {
                "value": "test2",
                "description": "測(cè)試appid2"
              }
            ],
            "providers":[
              {
                "name":"any"
              }
            ]
          }
      ]
      

      我們可以配置providers為any,這樣說(shuō)明開(kāi)發(fā)者除了可以配置test1test2外,當(dāng)配置其他值時(shí),也是允許的

      針對(duì)providers中的name屬性,主要有以下類(lèi)別供選擇:

      Name Description
      any Permits any additional value to be provided.
      class-reference Auto-completes the classes available in the project. Usually constrained by a base class that is specified by the target parameter.
      handle-as Handles the property as if it were defined by the type defined by the mandatory target parameter.
      logger-name Auto-completes valid logger names and logger groups. Typically, package and class names available in the current project can be auto-completed as well as defined groups.
      spring-bean-reference Auto-completes the available bean names in the current project. Usually constrained by a base class that is specified by the target parameter.
      spring-profile-name Auto-completes the available Spring profile names in the project.

      附錄

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多