SpringBoot基礎系列@Value 之字面量及 SpEL使用知識點介紹篇

【SpringBoot 基礎系列】@Value 之字面量及 SpEL 知識點介紹篇

承接上一篇博文【SpringBoot 基礎系列】@Value 中哪些你不知道的知識點 中說起到但沒有細說的知識點,這一篇博文未來看一下@Value除了綁定配置文件中的屬性配置以外,另外支持的兩種姿式java

  • 字面量表達式支持
  • SpEL 語法支持

<!-- more -->git

I. 項目環境

1. 項目依賴

本項目藉助SpringBoot 2.2.1.RELEASE + maven 3.5.3 + IDEA進行開發github

開一個 web 服務用於測試web

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

II. @Value 知識點

上一篇的博文知道經過${}能夠獲取配置文件中對應的配置值,接下來咱們看一下另外兩種常見的姿式redis

1. 字面量

字面量的使用比較簡單,直接在@Value註解中寫常量spring

一個 demo 以下app

@Value("1 + 2")
private String common;

上面這種初始化以後,common 的值會是 1 + 2;若是隻是這種用法,這個東西就有些雞肋了,我直接賦值不香嘛,爲啥還有這樣畫蛇添足呢?dom

固然現實中(至少我有限的代碼接觸中),純上面這種寫法的很少,更常見的是下面這種maven

@Value("demo_${auth.jwt.token}")
private String prefixConf;

字面量 + 配置聯合使用,如咱們的配置文件值爲spring-boot

auth:
  jwt:
    token: TOKEN.123

上面的 prefixConf 的取值,實際爲 demo_TOKEN.123

2. SpEL 表達式

@Value 另一個很強的使用姿式是支持 SpEL 表達式,至於 SpEL 是什麼鬼,推薦查看【SpringBoot 基礎系列】SpEL 語法掃盲與查詢手冊

2.1 基本姿式

使用姿式是 #{},表示這個大括弧裏面的走 SpEL 表達式,以下

/**
 * 字符串
 */
@Value("#{'abcd'}")
private String spelStr;

/**
 * 基本計算
 */
@Value("#{1 + 2}")
private String spelVal3;

/**
 * 列表
 */
@Value("#{{1, 2, 3}}")
private List<Integer> spelList;

/**
 * map
 */
@Value("#{{a: '123', b: 'cde'}}")
private Map spelMap;

上面是幾個基本的 case 了,字面量,表達式,列表/Map 等,SpEL 的基本使用姿式與掃盲博文中的沒有什麼區別,無外乎就是在外層多了一個${}

固然若是僅僅只是介紹上面幾個的話,就有點單調了,SpEL 一個比較強大的就是能夠訪問 bean 的屬性/方法,這就給了咱們不少的想像空間了

2.2 調用靜態方法:

在上面這個配置類com.git.hui.boot.properties.value.config.SpelProperties中添加一個靜態方法

public static String uuid() {
    return "spel_" + UUID.randomUUID().toString().replaceAll("_", ".");
}

而後咱們嘗試調用它

/**
 * 調用靜態方法
 */
@Value("#{T(com.git.hui.boot.properties.value.config.SpelProperties).uuid()}")
private String spelStaticMethod;

這樣spelStaticMethod就會是一個 "spel_" 開頭的隨機字符串了

請注意:若是在你的實際生產項目中,寫出這樣的代碼,那多半意味着離找下家不遠了

2.3 嵌套使用

接下來藉助 SpEL 與配置綁定的嵌套使用,來稍微調整下上面的實現(實際上下面這種用法也不常見,雖然沒問題,但這種代碼就屬於寫時一時爽,維護火葬場了 🙄)

/**
 * 調用靜態方法
 */
@Value("#{T(com.git.hui.boot.properties.value.config.SpelProperties).uuid('${auth.jwt.token}_')}")
private String spelStaticMethod;

public static String uuid(String prefix) {
    return prefix + UUID.randomUUID().toString().replaceAll("_", ".");
}

關於嵌套使用,下面再給出一個基礎的使用姿式,供打開思路用

/**
 * 嵌套使用,從配置中獲取值,而後執行SpEL語句
 */
@Value("#{'${auth.jwt.token}'.substring(2)}")
private String spelLen;

2.4 Bean 方法調用

最後再來一個訪問 bean 的方法的 case

定義一個 Service

@Service
public class RandomService {
    private AtomicInteger cnt = new AtomicInteger(1);

    public String randUid() {
        return cnt.getAndAdd(1) + "_" + UUID.randomUUID().toString();
    }
}

一個使用的姿式以下

/**
 * bean 方法訪問
 */
@Value("#{randomService.randUid()}")
private String spelBeanMethod;

3. 測試

最後給出一個注入的結果輸出,查看下有沒有什麼偏離預期的場景

@RestController
@SpringBootApplication
public class Application {

    @Autowired
    private SpelProperties spelProperties;

    @GetMapping("spel")
    public SpelProperties showSpel() {
        return spelProperties;
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}

4. 小結

本篇博文主要介紹了@Value除了綁定配置文件中的配置以外,另外兩種常見的 case

  • 字面量
  • SpEL 表達式:定義在#{}裏面

藉助 SpEL 的強大功能,徹底能夠發揮咱們的腦洞,讓@Value修飾的屬性初始化再也不侷限於簡單的配置文件,好比從 db,redis,http 獲取徹底是可行的嘛,無非就是一個表達式而已

固然這裏還存在一個待解決的問題,就是值刷新的支持,已知@Value只在 bean 初始化時執行一次,後續即使配置變動了,亦不會從新更改這個值,這種設計有好有壞,好處很明顯,配置的不變性能夠省去不少問題;缺點就是不靈活

那麼如何讓@Value的配置能夠動態刷新呢?

咱麼下篇博文見,我是一灰灰,歡迎關注長草的公衆號一灰灰blog

III. 不能錯過的源碼和相關知識點

0. 項目

配置系列博文

1. 一灰灰 Blog

盡信書則不如,以上內容,純屬一家之言,因我的能力有限,不免有疏漏和錯誤之處,如發現 bug 或者有更好的建議,歡迎批評指正,不吝感激

下面一灰灰的我的博客,記錄全部學習和工做中的博文,歡迎你們前去逛逛

一灰灰blog

相關文章
相關標籤/搜索