@Value竟然能玩出這么多花樣
大家好,我是蘇三,又跟大家見(jiàn)面了。
前言
對(duì)于從事java開(kāi)發(fā)工作的小伙伴來(lái)說(shuō),spring框架肯定再熟悉不過(guò)了。spring給開(kāi)發(fā)者提供了非常豐富的api,滿(mǎn)足我們?nèi)粘5墓ぷ餍枨蟆?/p>
如果想要?jiǎng)?chuàng)建bean實(shí)例,可以使用@Controller、@Service、@Repository、@Component等注解。
如果想要依賴(lài)注入某個(gè)對(duì)象,可以使用@Autowired和@Resource注解。
如果想要開(kāi)啟事務(wù),可以使用@Transactional注解。
如果想要?jiǎng)討B(tài)讀取配置文件中的某個(gè)系統(tǒng)屬性,可以使用@Value注解。
等等,還有很多。。。
前面幾種常用的注解,在我以往的文章《@Autowired的這些騷操作,你都知道嗎?》《聊聊spring事務(wù)失效的12種場(chǎng)景,太坑了》《驚呆了,spring中竟然有12種定義bean的方法》中已經(jīng)介紹過(guò)了,在這里就不過(guò)多講解了。
今天咱們重點(diǎn)聊聊@Value注解,因?yàn)樗且粋€(gè)非常有用,但極其容易被忽視的注解,絕大多數(shù)人可能只用過(guò)它的一部分功能,這是一件非常遺憾的事情。
所以今天有必要和大家一起,重新認(rèn)識(shí)一下@Value。
1. 由一個(gè)例子開(kāi)始
假如在UserService類(lèi)中,需要注入系統(tǒng)屬性到userName變量中。通常情況下,我們會(huì)寫(xiě)出如下的代碼:
@Service
public class UserService {
@Value("${susan.test.userName}")
private String userName;
public String test() {
System.out.println(userName);
return userName;
}
}
通過(guò)@Value注解指定系統(tǒng)屬性的名稱(chēng)susan.test.userName,該名稱(chēng)需要使用${}包起來(lái)。
這樣spring就會(huì)自動(dòng)的幫我們把對(duì)應(yīng)的系統(tǒng)屬性值,注入到userName變量中。
不過(guò),上面功能的重點(diǎn)是要在applicationContext.properties文件(簡(jiǎn)稱(chēng):配置文件)中配置同名的系統(tǒng)屬性:
#張三
susan.test.userName=\u5f20\u4e09
那么,名稱(chēng)真的必須完全相同嗎?
2. 關(guān)于屬性名
這時(shí)候,有些朋友可能會(huì)說(shuō):在@ConfigurationProperties配置類(lèi)中,定義的參數(shù)名可以跟配置文件中的系統(tǒng)屬性名不同。
比如,在配置類(lèi)MyConfig類(lèi)中定義的參數(shù)名是userName:
@Configuration
@ConfigurationProperties(prefix = "susan.test")
@Data
public class MyConfig {
private String userName;
}
而配置文件中配置的系統(tǒng)屬性名是:
susan.test.user-name=\u5f20\u4e09
類(lèi)中用的userName,而配置文件中用的user-name,不一樣。但測(cè)試之后,發(fā)現(xiàn)該功能能夠正常運(yùn)行。
配置文件中的系統(tǒng)屬性名用 駝峰標(biāo)識(shí) 或 小寫(xiě)字母加中劃線(xiàn)的組合,spring都能找到配置類(lèi)中的屬性名userName進(jìn)行賦值。
由此可見(jiàn),配置文件中的系統(tǒng)屬性名,可以跟配置類(lèi)中的屬性名不一樣。不過(guò),有個(gè)前提,前綴susan.test必須相同。
那么,@Value注解中定義的系統(tǒng)屬性名也可以不一樣嗎?
答案:不能。如果不一樣,啟動(dòng)項(xiàng)目時(shí)會(huì)直接報(bào)錯(cuò)。
此外,如果只在@Value注解中指定了系統(tǒng)屬性名,但實(shí)際在配置文件中沒(méi)有配置它,也會(huì)報(bào)跟上面一樣的錯(cuò)。
所以,@Value注解中指定的系統(tǒng)屬性名,必須跟配置文件中的相同。
3. 亂碼問(wèn)題
不知道細(xì)心的小伙伴們有沒(méi)有發(fā)現(xiàn),我配置的屬性值:張三,其實(shí)是轉(zhuǎn)義過(guò)的。
susan.test.userName=\u5f20\u4e09
為什么要做這個(gè)轉(zhuǎn)義?
假如在配置文件中配置中文的張三:
susan.test.userName=張三
最后獲取數(shù)據(jù)時(shí),你會(huì)發(fā)現(xiàn)userName竟然出現(xiàn)了亂碼:
?? ???
what?
為什么會(huì)出現(xiàn)亂碼?
答:在springboot的CharacterReader類(lèi)中,默認(rèn)的編碼格式是ISO-8859-1,該類(lèi)負(fù)責(zé).properties文件中系統(tǒng)屬性的讀取。如果系統(tǒng)屬性包含中文字符,就會(huì)出現(xiàn)亂碼。
那么,如何解決亂碼問(wèn)題呢?
目前主要有如下三種方案:
手動(dòng)將ISO-8859-1格式的屬性值,轉(zhuǎn)換成UTF-8格式。 設(shè)置encoding參數(shù),不過(guò)這個(gè)只對(duì)@PropertySource注解有用。 將中文字符用unicode編碼轉(zhuǎn)義。
顯然@Value不支持encoding參數(shù),所以方案2不行。
假如使用方案1,具體實(shí)現(xiàn)代碼如下:
@Service
public class UserService {
@Value(value = "${susan.test.userName}")
private String userName;
public String test() {
String userName1 = new String(userName.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
System.out.println();
return userName1;
}
}
確實(shí)可以解決亂碼問(wèn)題。
但如果項(xiàng)目中包含大量中文系統(tǒng)屬性值,每次都需要加這樣一段特殊轉(zhuǎn)換代碼。出現(xiàn)大量重復(fù)代碼,有沒(méi)有覺(jué)得有點(diǎn)惡心?
反轉(zhuǎn)我被惡心到了。
那么,如何解決代碼重復(fù)問(wèn)題呢?
答:將屬性值的中文內(nèi)容轉(zhuǎn)換成unicode。
類(lèi)似于這樣的:
susan.test.userName=\u5f20\u4e09
這種方式同樣能解決亂碼問(wèn)題,不會(huì)出現(xiàn)惡心的重復(fù)代碼。但需要做一點(diǎn)額外的轉(zhuǎn)換工作,不過(guò)這個(gè)轉(zhuǎn)換非常容易,因?yàn)橛鞋F(xiàn)成的在線(xiàn)轉(zhuǎn)換工具。
推薦使用這個(gè)工具轉(zhuǎn)換:http://www.jsons.cn/unicode/
在這里順便告訴你一個(gè)小秘密:如果你使用的是.yml或.yaml格式的配置文件,并不會(huì)出現(xiàn)中文亂碼問(wèn)題。
這又是為什么?
因?yàn)?yml或.yaml格式的配置文件,最終會(huì)使用UnicodeReader類(lèi)進(jìn)行解析,它的init方法中,首先讀取BOM文件頭信息,如果頭信息中有UTF8、UTF16BE、UTF16LE,就采用對(duì)應(yīng)的編碼,如果沒(méi)有,則采用默認(rèn)UTF8編碼。

需要注意的是:亂碼問(wèn)題一般出現(xiàn)在本地環(huán)境,因?yàn)楸镜刂苯幼x取的.properties配置文件。在dev、test、生產(chǎn)等環(huán)境,如果從zookeeper、apollo、nacos等配置中心中獲取系統(tǒng)參數(shù)值,走的是另外的邏輯,并不會(huì)出現(xiàn)亂碼問(wèn)題。
4.默認(rèn)值
有時(shí)候,默認(rèn)值是我們非常頭疼的問(wèn)題。
為什么這樣說(shuō)呢?
因?yàn)楹芏鄷r(shí)候使用java的默認(rèn)值,并不能滿(mǎn)足我們的日常工作需求。
比如有這樣一個(gè)需求:如果配置了系統(tǒng)屬性,userName就用配置的屬性值。如果沒(méi)有配置,則userName用默認(rèn)值susan。
有些朋友可能認(rèn)為可以這樣做:
@Value(value = "${susan.test.userName}")
private String userName = "susan";
在定義參數(shù)時(shí)直接給個(gè)默認(rèn)值,但如果仔細(xì)想想這招是行不通的的。因?yàn)樵O(shè)置userName默認(rèn)值的時(shí)機(jī),比@Value注解依賴(lài)注入屬性值要早,也就是說(shuō)userName初始化好了默認(rèn)值,后面還是會(huì)被覆蓋。
那么,到底該如何設(shè)置默認(rèn)值呢?
答:使用:。
例如:
@Value(value = "${susan.test.userName:susan}")
private String userName;
在需要設(shè)置默認(rèn)值的系統(tǒng)屬性名后,加:符號(hào)。緊接著,在:右邊設(shè)置默認(rèn)值。
建議大家平時(shí)在使用@Value時(shí),盡量都設(shè)置一個(gè)默認(rèn)值。如果不需要默認(rèn)值,寧可設(shè)置一個(gè)空。比如:
@Value(value = "${susan.test.userName:}")
private String userName;
為什么這么說(shuō)?
假如有這種場(chǎng)景:在business層中包含了UserService類(lèi),business層被api服務(wù)和job服務(wù)都引用了。但UserService類(lèi)中@Value的userName只在api服務(wù)中有用,在job服務(wù)中根本用不到該屬性。
對(duì)于job服務(wù)來(lái)說(shuō),如果不在.properties文件中配置同名的系統(tǒng)屬性,則服務(wù)啟動(dòng)時(shí)就會(huì)報(bào)錯(cuò)。
這個(gè)坑,我之前踩過(guò)多次。所以,建議大家,使用@Value注解時(shí),最好給參數(shù)設(shè)置一個(gè)默認(rèn)值,以防止出現(xiàn)類(lèi)似的問(wèn)題。
5. static變量
前面我們已經(jīng)見(jiàn)識(shí)過(guò),如何使用@Value注解,給類(lèi)的成員變量注入系統(tǒng)屬性值。
那么,問(wèn)題來(lái)了,靜態(tài)變量可以自動(dòng)注入系統(tǒng)屬性值不?
我們一起看看,假如將上面的userName定義成static的:
@Value("${susan.test.userName}")
private static String userName;
程序可以正常啟動(dòng),但是獲取到userName的值卻是null。
由此可見(jiàn),被static修飾的變量通過(guò)@Value會(huì)注入失敗。
作為好奇寶寶的你,此時(shí)肯定想問(wèn):如何才能給靜態(tài)變量注入系統(tǒng)屬性值呢?
答:這就需要使用如下的騷代碼了:
@Service
public class UserService {
private static String userName;
@Value("${susan.test.userName}")
public void setUserName(String userName) {
UserService.userName = userName;
}
public String test() {
return userName;
}
}
提供一個(gè)靜態(tài)參數(shù)的setter方法,在該方法上使用@Value注入屬性值,并且同時(shí)在該方法中給靜態(tài)變量賦值。
有些細(xì)心的朋友可能會(huì)發(fā)現(xiàn),@Value注解在這里竟然使用在setUserName方法上了,也就是對(duì)應(yīng)的setter方法,而不是在變量上。
有趣,有趣,這種用法有點(diǎn)高端喔。
不過(guò),通常情況下,我們一般會(huì)在pojo實(shí)體類(lèi)上,使用lombok的@Data、@Setter、@Getter等注解,在編譯時(shí)動(dòng)態(tài)增加setter或getter方法,所以@Value用在方法上的場(chǎng)景其實(shí)不多。
6.變量類(lèi)型
上面的內(nèi)容,都是用的字符串類(lèi)型的變量進(jìn)行舉例的。其實(shí),@Value注解還支持其他多種類(lèi)型的系統(tǒng)屬性值的注入。
6.1 基本類(lèi)型
眾所周知,在Java中的基本數(shù)據(jù)類(lèi)型有4類(lèi)8種,然我們一起回顧一下:
整型:byte、short、int、long 浮點(diǎn)型:float、double 布爾型:boolean 字符型:char
相對(duì)應(yīng)地提供了8種包裝類(lèi):
整型:Byte、Short、Integer、Long 浮點(diǎn)型:Float、Double 布爾型:Boolean 字符型:Character
@Value注解對(duì)這8中基本類(lèi)型和相應(yīng)的包裝類(lèi),有非常良好的支持,例如:
@Value("${susan.test.a:1}")
private byte a;
@Value("${susan.test.b:100}")
private short b;
@Value("${susan.test.c:3000}")
private int c;
@Value("${susan.test.d:4000000}")
private long d;
@Value("${susan.test.e:5.2}")
private float e;
@Value("${susan.test.f:6.1}")
private double f;
@Value("${susan.test.g:false}")
private boolean g;
@Value("${susan.test.h:h}")
private char h;
@Value("${susan.test.a:1}")
private byte a1;
@Value("${susan.test.b:100}")
private Short b1;
@Value("${susan.test.c:3000}")
private Integer c1;
@Value("${susan.test.d:4000000}")
private Long d1;
@Value("${susan.test.e:5.2}")
private Float e1;
@Value("${susan.test.f:6.1}")
private Double f1;
@Value("${susan.test.g:false}")
private Boolean g1;
@Value("${susan.test.h:h}")
private Character h1;
有了這些常用的數(shù)據(jù)類(lèi)型,我們?cè)诙x變量類(lèi)型時(shí),可以非常愉快的玩耍了,不用做額外的轉(zhuǎn)換。
6.2 數(shù)組
但只用上面的基本類(lèi)型是不夠的,特別是很多需要批量處理數(shù)據(jù)的場(chǎng)景中。這時(shí)候可以使用數(shù)組,它在日常開(kāi)發(fā)中使用的頻率很高。
我們?cè)诙x數(shù)組時(shí)可以這樣寫(xiě):
@Value("${susan.test.array:1,2,3,4,5}")
private int[] array;
spring默認(rèn)使用逗號(hào)分隔參數(shù)值。
如果用空格分隔,例如:
@Value("${susan.test.array:1 2 3 4 5}")
private int[] array;
spring會(huì)自動(dòng)把空格去掉,導(dǎo)致數(shù)據(jù)中只有一個(gè)值:12345,注意千萬(wàn)別搞錯(cuò)了。
順便說(shuō)一下,定義數(shù)組的時(shí)候,里面還是有挺多門(mén)道的。比如上面列子中,我的數(shù)據(jù)是:1,2,3,4,5。
如果我們把數(shù)組定義成:short、int、long、char、string類(lèi)型,spring是可以正常注入屬性值的。
但如果把數(shù)組定義成:float、double類(lèi)型,啟動(dòng)項(xiàng)目時(shí)就會(huì)直接報(bào)錯(cuò)。
小伙伴們,下巴驚掉了沒(méi)?
按理說(shuō),1,2,3,4,5用float、double是能夠表示的呀,為什么會(huì)報(bào)錯(cuò)?
如果使用int的包裝類(lèi),比如:
@Value("${susan.test.array:1,2,3,4,5}")
private Integer[] array;
啟動(dòng)項(xiàng)目時(shí)同樣會(huì)報(bào)上面的異常。
此外,定義數(shù)組時(shí)一定要注意屬性值的類(lèi)型,必須完全一致才可以,如果出現(xiàn)下面這種情況:
@Value("${susan.test.array:1.0,abc,3,4,5}")
private int[] array;
屬性值中包含了1.0和abc,顯然都無(wú)法將該字符串轉(zhuǎn)換成int。
6.3 集合類(lèi)
有了基本類(lèi)型和數(shù)組,的確讓我們更加方便了。但對(duì)數(shù)據(jù)的處理,只用數(shù)組這一種數(shù)據(jù)結(jié)構(gòu)是遠(yuǎn)遠(yuǎn)不夠的,下面給大家介紹一下其他的常用數(shù)據(jù)結(jié)構(gòu)。
6.3.1 List
List是數(shù)組的變種,它的長(zhǎng)度是可變的,而數(shù)組的長(zhǎng)度是固定的。
我們看看List是如何注入屬性值的:
@Value("${susan.test.list}")
private List<String> list;
最關(guān)鍵的是看配置文件:
susan.test.list[0]=10
susan.test.list[1]=11
susan.test.list[2]=12
susan.test.list[3]=13
當(dāng)你滿(mǎn)懷希望的啟動(dòng)項(xiàng)目,準(zhǔn)備使用這個(gè)功能的時(shí)候,卻發(fā)現(xiàn)竟然報(bào)錯(cuò)了。
what?
看來(lái)@Value不支持這種直接的List注入。
那么,如何解決這個(gè)問(wèn)題呢?
有人說(shuō)用@ConfigurationProperties。
需要定義一個(gè)MyConfig類(lèi):
@Configuration
@ConfigurationProperties(prefix = "susan.test")
@Data
public class MyConfig {
private List<String> list;
}
然后在調(diào)用的地方這樣寫(xiě):
@Service
public class UserService {
@Autowired
private MyConfig myConfig;
public String test() {
System.out.println(myConfig.getList());
return null;
}
}
這種方法確實(shí)能夠完成List注入。但是,只能說(shuō)明@ConfigurationProperties注解的強(qiáng)大,跟@Value有半毛錢(qián)的關(guān)系?
答:沒(méi)有。
那么,問(wèn)題來(lái)了,用@Value如何實(shí)現(xiàn)這個(gè)功能呢?
答:使用spring的EL表達(dá)式。
List的定義改成:
@Value("#{'${susan.test.list}'.split(',')}")
private List<String> list;
使用#號(hào)加大括號(hào)的EL表達(dá)式。
然后配置文件改成:
susan.test.list=10,11,12,13
跟定義數(shù)組時(shí)的配置文件一樣。
6.3.2 Set
Set也是一種保存數(shù)據(jù)的集合,它比較特殊,里面保存的數(shù)據(jù)不會(huì)重復(fù)。
我們可以這樣定義Set:
@Value("#{'${susan.test.set}'.split(',')}")
private Set<String> set;
配置文件是這樣的:
susan.test.set=10,11,12,13
Set跟List的用法極為相似。
但為了證明本節(jié)的獨(dú)特之處,我打算說(shuō)點(diǎn)新鮮的內(nèi)容。
如何給List或者Set設(shè)置默認(rèn)值空呢?
有些朋友可能會(huì)說(shuō):這還不簡(jiǎn)單,直接在@Value的$表達(dá)式后面加個(gè):號(hào)不就行了。
具體代碼如下:
@Value("#{'${susan.test.set:}'.split(',')}")
private Set<String> set;
結(jié)果卻跟想象中不太一樣:
Set集合怎么不是空的,而是包含了一個(gè)空字符串的集合?
好吧,那我在:號(hào)后加null,總可以了吧?
Set集合也不是空的,而是包含了一個(gè)"null"字符串的集合。
這也不行,那也不行,該如何是好?
答:使用EL表達(dá)式的empty方法。
具體代碼如下:
@Value("#{'${susan.test.set:}'.empty ? null : '${susan.test.set:}'.split(',')}")
private Set<String> set;
運(yùn)行之后,結(jié)果對(duì)了:
其實(shí)List也有類(lèi)似的問(wèn)題,也能使用該方法解決問(wèn)題。
在這里溫馨的提醒一下,該判斷的表達(dá)式比較復(fù)雜,自己手寫(xiě)非常容易寫(xiě)錯(cuò),建議復(fù)制粘貼之后根據(jù)實(shí)際需求改改。
6.3.3 Map
還有一種比較常用的集合是map,它支持key/value鍵值對(duì)的形式保存數(shù)據(jù),并且不會(huì)出現(xiàn)相同key的數(shù)據(jù)。
我們可以這樣定義Map:
@Value("#{${susan.test.map}}")
private Map<String, String> map;
配置文件是這樣的:
susan.test.map={"name":"蘇三", "age":"18"}
這種用法跟上面稍微有一點(diǎn)區(qū)別。
設(shè)置默認(rèn)值的代碼如下:
@Value("#{'${susan.test.map:}'.empty ? null : '${susan.test.map:}'}")
private Map<String, String> map;
7 EL高端玩法
前面我們已經(jīng)見(jiàn)識(shí)過(guò)spring EL表達(dá)式的用法了,在設(shè)置空的默認(rèn)值時(shí)特別有用。
其實(shí),empty方法只是它很普通的用法,還有更高端的用法,不信我們一起看看。
7.1 注入bean
以前我們注入bean,一般都是用的@Autowired或者@Resource注解。例如:
@Service
public class RoleService {
public String getRoleName() {
return "管理員";
}
}
@Service
public class UserService {
@Autowired
private RoleService roleService;
public String test() {
System.out.println(roleService.getRoleName());
return null;
}
}
但我要告訴你的是@Value注解也可以注入bean,它是這么做的:
@Value("#{roleService}")
private RoleService roleService;
通過(guò)這種方式,可以注入id為roleService的bean。
7.2 bean的變量和方法
通過(guò)EL表達(dá)式,@Value注解已經(jīng)可以注入bean了。既然能夠拿到bean實(shí)例,接下來(lái),可以再進(jìn)一步。
在RoleService類(lèi)中定義了:成員變量、常量、方法、靜態(tài)方法。
@Service
public class RoleService {
public static final int DEFAULT_AGE = 18;
public int id = 1000;
public String getRoleName() {
return "管理員";
}
public static int getParentId() {
return 2000;
}
}
在調(diào)用的地方這樣寫(xiě):
@Service
public class UserService {
@Value("#{roleService.DEFAULT_AGE}")
private int myAge;
@Value("#{roleService.id}")
private int id;
@Value("#{roleService.getRoleName()}")
private String myRoleName;
@Value("#{roleService.getParentId()}")
private String myParentId;
public String test() {
System.out.println(myAge);
System.out.println(id);
System.out.println(myRoleName);
System.out.println(myParentId);
return null;
}
}
在UserService類(lèi)中通過(guò)@Value可以注入:成員變量、常量、方法、靜態(tài)方法獲取到的值,到相應(yīng)的成員變量中。
一下子有沒(méi)有豁然開(kāi)朗的感覺(jué),有了這些,我們可以通過(guò)@Value注解,實(shí)現(xiàn)更多的功能了,不僅僅限于注入系統(tǒng)屬性。
7.3 靜態(tài)類(lèi)
前面的內(nèi)容都是基于bean的,但有時(shí)我們需要調(diào)用靜態(tài)類(lèi),比如:Math、xxxUtil等靜態(tài)工具類(lèi)的方法,該怎么辦呢?
答:用T加括號(hào)。
示例1:
@Value("#{T(java.io.File).separator}")
private String path;
可以注入系統(tǒng)的路徑分隔符到path中。
示例2:
@Value("#{T(java.lang.Math).random()}")
private double randomValue;
可以注入一個(gè)隨機(jī)數(shù)到randomValue中。
7.4 邏輯運(yùn)算
通過(guò)上面介紹的內(nèi)容,我們可以獲取到絕大多數(shù)類(lèi)的變量和方法的值了。但有了這些值,還不夠,我們能不能在EL表達(dá)式中加點(diǎn)邏輯?
拼接字符串:
@Value("#{roleService.roleName + '' + roleService.DEFAULT_AGE}")
private String value;
邏輯判斷:
@Value("#{roleService.DEFAULT_AGE > 16 and roleService.roleName.equals('蘇三')}")
private String operation;
三目運(yùn)算:
@Value("#{roleService.DEFAULT_AGE > 16 ? roleService.roleName: '蘇三' }")
private String realRoleName;
還有很多很多功能,我就不一一列舉了。
EL表達(dá)式實(shí)在太強(qiáng)大了,對(duì)這方面如果感興趣的小伙伴可以找我私聊。
8 ${}和#{}的區(qū)別
上面巴拉巴拉說(shuō)了這么多@Value的牛逼用法,歸根揭底就是${}和#{}的用法。
下面重點(diǎn)說(shuō)說(shuō)${}和#{}的區(qū)別,這可能是很多小伙伴比較關(guān)心的話(huà)題。
8.1 ${}
主要用于獲取配置文件中的系統(tǒng)屬性值。
例如:
@Value(value = "${susan.test.userName:susan}")
private String userName;
通過(guò):可以設(shè)置默認(rèn)值。如果在配置文件中找不到susan.test.userName的配置,則注入時(shí)用默認(rèn)值。
如果在配置文件中找不到susan.test.userName的配置,也沒(méi)有設(shè)置默認(rèn)值,則啟動(dòng)項(xiàng)目時(shí)會(huì)報(bào)錯(cuò)。
8.2 #{}
主要用于通過(guò)spring的EL表達(dá)式,獲取bean的屬性,或者調(diào)用bean的某個(gè)方法。還有調(diào)用類(lèi)的靜態(tài)常量和靜態(tài)方法。
@Value("#{roleService.DEFAULT_AGE}")
private int myAge;
@Value("#{roleService.id}")
private int id;
@Value("#{roleService.getRoleName()}")
private String myRoleName;
@Value("#{T(java.lang.Math).random()}")
private double randomValue;
如果是調(diào)用類(lèi)的靜態(tài)方法,則需要加T(包名 + 方法名稱(chēng))。
例如:T(java.lang.Math)。
好了,今天的內(nèi)容就介紹到這里,希望對(duì)你會(huì)有所幫助。


課程:《Java進(jìn)階:Web開(kāi)發(fā)實(shí)戰(zhàn)》
講師:顏群
課程介紹:本視頻課程將系統(tǒng)學(xué)習(xí)Java Web基礎(chǔ)知識(shí)及常用功能,通過(guò)包含JSP/Servlet/上傳/下載/分頁(yè)/MVC/三層架構(gòu)等知識(shí)講解來(lái)進(jìn)行Web網(wǎng)站開(kāi)發(fā),將所學(xué)知識(shí)點(diǎn)及常用功能進(jìn)行串聯(lián),逐步深入、加深記憶,最終達(dá)成Java Web小白入門(mén)Web網(wǎng)站開(kāi)發(fā)!
課程特點(diǎn):
1.每個(gè)章節(jié)大概15分鐘左右。
2.建議堅(jiān)持每天抽出2-3小時(shí)進(jìn)行學(xué)習(xí),22天完成Javaweb的學(xué)習(xí)
3.該課程采用視頻教學(xué)模式,通過(guò)多個(gè)知識(shí)層面進(jìn)行講解,幫助小伙伴輕松更好的學(xué)習(xí)JavaWeb開(kāi)發(fā)。
4.有一定基礎(chǔ)java編程基礎(chǔ)的學(xué)員學(xué)習(xí)web開(kāi)發(fā),只需學(xué)完本課程即可。
學(xué)習(xí)方式:掃碼 ↓ 立即前往課程界面

