Spring之@Value註解
@Value 註解可以用來將外部的值動態注入到 Bean 中,在 @Value 註解中,可以使用 ${} 或 #{}。${} 與 #{} 的區別如下:
(1)@Value("${}"):可以獲取對應屬性檔案中定義的屬性值。
(2)@Value("#{}"):表示 SpEl 表示式通常用來獲取 bean 的屬性,或者呼叫 bean 的某個方法。
@Value 註解的常用使用方式如下:
一、注入普通字串
屬性檔案內容如下:
str1=hello world
Java程式碼如下:
// 直接將字串賦值給 str 屬性 @Value("hello world") private String str;// 從屬性檔案中獲取值 @Value("${str1}") private String str1; // 結果:hello world
如果在屬性檔案中沒有定義 str1 屬性名,則 @Value 會丟擲如下錯誤“java.lang.IllegalArgumentException: Could not resolve placeholder 'str1' in value "${str1}"”。我們可以在 str1 屬性不存在時,指定預設值,即使沒有定義 str2 也不會丟擲錯誤,而是返回預設值。如下:
@Value("${str2:defaultValue}") private String str2; //結果:defaultValue
二、注入作業系統屬性
可以利用 @Value 注入作業系統屬性。這裡我們不能使用“${}”去獲取作業系統屬性。如下:
@Value("${systemProperties['os.name']}") private String osName;
上面程式碼將丟擲 java.lang.IllegalArgumentException: Could not resolve placeholder 'systemProperties['os.name']' in value "${systemProperties['os.name']}" 錯誤資訊。你需要將 ${} 改為 #{},如下:
@Value("#{systemProperties['os.name']}") private String osName; // 結果:Windows 10
三、注入表示式結果
在 @Value 中,允許我們使用表示式,然後自動計算表示式的結果。將結果複製給指定的變數。如下:
// 生成一個隨機數 @Value("#{ T(java.lang.Math).random() * 1000.0 }") private double randomNumber; // 使用 System 類獲取系統環境變數 PATH @Value("#{ T(java.lang.System).getenv('path') }") private String path;
四、注入其他Bean屬性
在 @Value 註解中,也可以將其他 bean 的屬性值注入到當前 bean。如下:
// 其他Bean @Component public class OtherBean { @Value("OtherBean的NAME屬性") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } // 用法 @Component public class MyBean { @Value("#{otherBean.name}") private String fromAnotherBean; // ... }
注意,其他 bean 使用@Component 時,如果沒有指定名稱,則預設為類名首字母小寫,如:otherBean 。當然我們也可以使用@Component("myName") 形式,指定其他 bean 的名稱,此時,訪問則需要使用 @Value("#{myName.name}")。如下:
// 其他bean,自定義名稱為 myBeans @Component("myBeans") public class OtherBean2 { @Value("OtherBean的NAME屬性") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } // 用法 @Component public class MyBean { @Value("#{myBeans.name}") private String fromAnotherBean2; // ... }
五、注入資源
在 @Value 註解中,也可以用來注入資源(Resource),如:檔案資源、URL網路資源等。如下:
// 注入檔案資源 @Value("classpath:props/application.properties") private Resource fileResource; // 注入URL資源 @Value("https://www.hxstrive.com") private Resource urlResource;
完整程式碼如下:
@Service public class ValueDemo5 { // 注入檔案資源 @Value("classpath:props/application.properties") private Resource fileResource; // 注入URL資源 @Value("https://www.hxstrive.com") private Resource urlResource; public static void main(String[] args) throws Exception { ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContent-value.xml"); ValueDemo5 demo = context.getBean(ValueDemo5.class); // 輸出檔案資源內容 String fileContent = FileUtils.readFileToString( demo.getFileResource().getFile(), "UTF-8"); System.out.println(fileContent); // 輸出URL資源內容 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); BufferedInputStream inputStream = new BufferedInputStream( demo.getUrlResource().getInputStream()); byte[] buffer = new byte[2048]; int len; while((len = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, len); } System.out.println(new String(outputStream.toByteArray(), "UTF-8")); } public Resource getFileResource() { return fileResource; } public void setFileResource(Resource fileResource) { this.fileResource = fileResource; } public Resource getUrlResource() { return urlResource; } public void setUrlResource(Resource urlResource) { this.urlResource = urlResource; } }
六、@Value注入static屬性
一般@Value是使用在非靜態方法上的,對於靜態方法,以下做法是無效的:
@Value("${myProp}") public static String myProp;
如果要向靜態屬性注入值,可以使用set方法注入,如下:
private static String str1; @Value("${str1}") public void setStr1(String str1) { System.out.println("setStr1 ===> " + str1); ValueDemo7.str1 = str1; }
如果將 setStr1() 方法設定成 static,則 Spring 將丟擲如下告警資訊:
13:26:34 WARN [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor] - Autowired annotation is not supported on static methods: public static void com.huangx.spring4.value.ValueDemo7.setStr1(java.lang.String)
七、引用外部屬性檔案
通過 @Value 將外部配置檔案的值動態注入到Bean中。配置檔案主要有兩類:
application.properties
在 spring boot 啟動時預設載入此檔案 application.properties,spring 則需要我們配置:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <!-- 設定如果沒有找到匹配的系統屬性,是否搜尋匹配的系統環境變數 --> <property name="searchSystemEnvironment" value="true" /> <!-- 設定如何檢查系統屬性(SYSTEM_PROPERTIES_MODE_FALLBACK=1) --> <property name="systemPropertiesMode" value="1"/> <!-- 載入屬性檔案,指定屬性檔案地址,可以指定多個 --> <property name="locations"> <list> <value>classpath:props/application.properties</value> </list> </property> </bean>
自定義屬性檔案
自定義屬性檔案通過 @PropertySource 載入,@PropertySource 可以同時載入多個檔案,也可以載入單個檔案。如果第一個屬性檔案和第二屬性檔案存在相同key,則最後一個屬性檔案裡的key起作用(前面屬性檔案的key將被覆蓋)。載入檔案的路徑也可以配置變數,如下面例項中 config.properties 屬性檔案的 ${env.model}(用來指定開發環境模式,如:dev-開發環境、prod-生產環境、test-測試環境)。屬性檔案定義如下:
# config.properties 檔案 env.model=dev # config_dev.properties 檔案 name= # config_prod.properties 檔案 name= # config_test.properties 檔案 name=
java 程式碼如下:
// 引入多個屬性配置檔案 @Component @PropertySource({ "classpath:config.properties", "classpath:config_${env.model}.properties" }) public class MyBean { }
本文轉載自:https://www.hxstrive.com/article/854.htm