[Day - 20] - Spring 一日优雅组态配置就上手

前提摘要

无论何种系统,都需要有一个组态设定的位置,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的工作原理


<<:  企划实现(20)

>>:  【第二一天 - Flutter Blue 蓝芽文件说明】

Day 30: 关於 Design Pattern,来点心理测验吧

缘由 现在对模式有个初步的了解,想试着写出「设计模式」的心理测验。 测验开始 问题区 问题 1 你这...

让Python GUI 画面在最前方显示/ 最小化显示/ 隐藏桌面图示的方法

很多时候,刚程序开启後有可能因为使用者操作的因素就让正在跑的程序被盖住了。尤其是在使用键盘滑鼠精灵控...

15. 做对事是不够的,你还必须要有影响力。

前言 这篇演讲适合所有人听,特别是当你觉得「为什麽我明明在做对的事情,但大家都不接受我的意见」时,...

[Day 24] Android Studio 七日陨石开发:安装与创建第一个专案 (下)

前言 昨天我们安装好Android Studio, 并且建立了一个专案叫做AIFER。 现在我们尝试...

13.unity 文字&关闭游戏

今天要新增一个按Esc实行关闭游戏的功能,制作这个功能的用法当然要告诉玩家啦! 利用canvas的t...