1. 程式人生 > >【Spring註解驅動開發】如何使用@Value註解為bean的屬性賦值,我們一起吊打面試官!

【Spring註解驅動開發】如何使用@Value註解為bean的屬性賦值,我們一起吊打面試官!

## 寫在前面 > 在之前的文章中,我們探討了如何向Spring的IOC容器中註冊bean元件,講解了有關bean元件的生命週期的知識。今天,我們就來一起聊聊@Value註解的用法。 > > 專案工程原始碼已經提交到GitHub:[https://github.com/sunshinelyz/spring-annotation](https://github.com/sunshinelyz/spring-annotation) ## @Value註解 Spring中的@Value註解可以為bean中的屬性賦值。我們先來看看@Value註解的原始碼,如下所示。 ```java package org.springframework.beans.factory.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Value { String value(); } ``` 從@Value註解的原始碼,我們可以看出:@Value註解可以標註在欄位、方法、引數、註解上,在程式執行期間生效。 ## @Value註解用法 ### 1.不通過配置檔案注入屬性的情況 通過@Value將外部的值動態注入到Bean中,使用的情況有: * 注入普通字串 ```java @Value("normal") private String normal; // 注入普通字串 ``` * 注入作業系統屬性 ```java @Value("#{systemProperties['os.name']}") private String systemPropertiesName; // 注入作業系統屬性 ``` * 注入表示式結果 ```java @Value("#{ T(java.lang.Math).random() * 100.0 }") private double randomNumber; //注入表示式結果 ``` * 注入其他Bean屬性 ```java @Value("#{person.name}") private String name; // 注入其他Bean屬性:注入person物件的屬性name ``` * 注入檔案資源 ```java @Value("classpath:io/mykit/spring/config/config.properties") private Resource resourceFile; // 注入檔案資源 ``` * 注入URL資源 ```java @Value("http://www.baidu.com") private Resource url; // 注入URL資源 ``` ### 2.通過配置檔案注入屬性的情況 通過@Value(“${app.name}”)語法將屬性檔案的值注入到bean的屬性中,如下所示。 ```java @Component // 引入外部配置檔案組:${app.configinject}的值來自config.properties。 // 如果相同 @PropertySource({"classpath:io/mykit/spring/config/config.properties", "classpath:io/mykit/spring/config/config_${anotherfile.configinject}.properties"}) public class ConfigurationFileInject{ // 這裡的值來自application.properties,spring boot啟動時預設載入此檔案 @Value("${app.name}") private String appName; // 注入第一個配置外部檔案屬性 @Value("${book.name}") private String bookName; // 注入第二個配置外部檔案屬性 @Value("${book.name.placeholder}") private String bookNamePlaceholder; // 注入環境變數物件,儲存注入的屬性值 @Autowired private Environment env; public String toString(){ StringBuilder sb = new StringBuilder(); sb.append("bookName=").append(bookName).append("\r\n") .append("bookNamePlaceholder=").append(bookNamePlaceholder).append("\r\n") .append("appName=").append(appName).append("\r\n") .append("env=").append(env).append("\r\n") // 從eniroment中獲取屬性值 .append("env=").append(env.getProperty("book.name.placeholder")).append("\r\n"); return sb.toString(); } } ``` ### 3.@Value中\#{..}和${...}的區別 我們這裡提供一個測試屬性檔案:advance_value_inject.properties,大致的內容如下所示。 ```bash server.name=server1,server2,server3 author.name=binghe ``` 測試類AdvanceValueInject:引入advance_value_inject.properties檔案,作為屬性的注入 ```java @Component @PropertySource({"classpath:io/mykit/spring/config/advance_value_inject.properties"}) public class AdvanceValueInject { ... } ``` **${...}的用法** {}裡面的內容必須符合SpEL表示式, 通過@Value(“${spelDefault.value}”)可以獲取屬性檔案中對應的值,但是如果屬性檔案中沒有這個屬性,則會報錯。可以通過賦予預設值解決這個問題,如下所示。 ```java @Value("${author.name:binghe}") ``` 上述程式碼的含義表示向bean的屬性中注入配置檔案中的author.name屬性的值,如果配置檔案中沒有author.name屬性,則向bean的屬性中注入預設值binghe。例如下面的程式碼片段。 ```java @Value("${author.name:binghe}") private String name; ``` **#{…}的用法** ```java // SpEL:呼叫字串Hello World的concat方法 @Value("#{'Hello World'.concat('!')}") private String helloWorld; // SpEL: 呼叫字串的getBytes方法,然後呼叫length屬性 @Value("#{'Hello World'.bytes.length}") private String helloWorldbytes; ``` **${…}和#{…}混合使用** `${...}和#{...}可以混合使用,如下文程式碼執行順序:通過${server.name}從屬性檔案中獲取值並進行替換,然後就變成了 執行SpEL表示式{‘server1,server2,server3’.split(‘,’)}。` ```java // SpEL: 傳入一個字串,根據","切分後插入列表中, #{}和${}配置使用(注意單引號,注意不能反過來${}在外面,#{}在裡面) @Value("#{'${server.name}'.split(',')}") priv