iT邦幫忙

2021 iThome 鐵人賽

DAY 20
0

前提摘要

無論何種系統,都需要有一個組態設定的位置,Spring很貼心的提供預設*.properies及*.yaml兩種預設的組態參數檔,此時Spring 提供了兩種註解模式提供開發者坐接取組態參數值,分別為@ConfigurationProperties及@Value兩種註解模式,此前者可透過字首進行鎖定,後者可直接透過整段參數關鍵詞進行注入其值,Spring透過此兩項註解可取代各位開發者早期既有的Properties()或System.setProperty(key,value)兩項參數配置元件,以下將透過範例給各位開發者做詳細的敘述。

範例說明與原理介紹

本章節提供兩種註解範例實作,整合前兩天的開發成果在延續下去,@ConfigurationProperties為一種將配置的文字訊息,自動封裝成一個類別實體,@Value則為自動的轉為某種特定屬性封裝類別,如:String.class,Integer.class or Long.class, etc),以下我們就直接透過程式碼範例進行講解。

範例一、參數檔[application.properties]參數如下

sea.food.api.china=china
sea.food.api.taiwan=taiwan

sea.food.company.name = Weisting SEA Food Retailer
sea.food.company.ceo = Darius Weisting
sea.food.company.capital= 6000000
sea.food.company.address =No. 88, Ln. 888, Sec. 5, Minzu Rd., Yangmei Dist., Taoyuan City 326002 , Taiwan (R.O.C.)
sea.food.company.uniformNumber = 86633399
sea.food.company.createdDate= 2021/10/05

sea.food.company.version = v1.0.1

範例一、將參數透過prefix字首為sea.food.company,封裝成類別實體為CompanyInformationConfig,而InformationController中置放@Value註解將配置參數檔中的sea.food.company.version的值注入version欄位,透過API即可取得相關資訊。

@Configuration
@ConfigurationProperties(
        prefix = "sea.food.company",
        ignoreInvalidFields=true
)
public class CompanyInformationConfig {
    String name;
    String ceo;
    Integer capital;
    String address;
    String uniformNumber;
    @DateTimeFormat(pattern = "YYYY/mm/dd")
    Date createdDate;

    .....
    .....
    .....
}


@RestController
public class InformationController extends ControllerBase {

    @Value("${sea.food.company.version}")
    String version;

    @Autowired
    private CompanyInformationConfig config;

    @GetMapping(
            value="/about"
    )
    ResponseEntity<Map> seaFoodVersion() {
        Map<String,Object> informationMap = new LinkedHashMap<String, Object>();
        informationMap.put("version",version);
        informationMap.put("name",config.getName());
        informationMap.put("ceo",config.getCeo());
        informationMap.put("capital",config.getCapital());
        informationMap.put("address",config.getAddress());
        informationMap.put("uniformNumber",config.getUniformNumber());
        informationMap.put("createdDate",config.getCreatedDate());
        return new ResponseEntity<>(informationMap, HttpStatus.OK);

    }
}

範例一、測試結果,可完整的取得其參數檔資訊
image

範例二、透過參數檔(${sea.food.api.taiwan})進行注入Sea Food Restful API 路徑位置

@RestController
public class ProductController extends ControllerBase{
    @Resource(name="seaFoodRetailService",type = SeaFoodRetailerService.class)
    SeaFoodRetailerService seaFoodRetailService;

    @GetMapping(
            value="/${sea.food.api.taiwan}/list"
    )
    List<SeaFood> listSeaFood() {
        return seaFoodRetailService.listSeaFoodProducts();

    }

    @GetMapping(
            value="/${sea.food.api.taiwan}/find/{id}",
            produces = MediaType.APPLICATION_JSON_VALUE,
            consumes = MediaType.APPLICATION_JSON_VALUE
    )
    ResponseEntity<SeaFood> findSeaFoodById(@PathVariable("id") String id) throws ResourceNotFoundException {
        Optional<SeaFood> seaFood =  seaFoodRetailService.findProductById(id);
        if (!seaFood.isPresent())
            throw new ResourceNotFoundException();
        return new ResponseEntity<SeaFood>(
                seaFood.get()
                , HttpStatus.OK
        );
    }
    .....
    .....
    
 }

範例二、測試結果可成功取得數據
image

根據以上小編所範例提供的範例,我們可以看出所有的註解模式的value值都是可透過參數檔進行注入的囉!

核心架構敘述

透過下圖一,入口點為AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization,並透過ConfigurationPropertiesBindingPostProcessorbind(ConfigurationPropertiesBean bean)進行串接與獲取該組態配置檔元件。

圖一 ConfigurationProperties Bean實體配置流程
image

透過下圖二,入口點為BeanConfigurerSupport.configureBean方法,並透過AbstractAutowireCapableBeanFactory.populateBean進行觸發PropertyValues元件中postProcessPropertyValues的方法以獲取相對應的參數值。

圖二 Value 參數值獲取流程
image

Sample Source

Spring-sample-config

Reference Url

SpringBoot源码解析之ConfigurationProperties原理

springboot中@Value的工作原理


上一篇
[Day - 19] - Spring 例外處理之優雅化客製化錯誤訊息原理與設計
下一篇
[Day - 21] - 規律的一天從Spring Scheduled 開始
系列文
Wow ! There is no doubt about Learn Spring framework in a month.30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言