@Value
用來注入某值,值可以是 Java 基本型態、字串,搭配 PlaceHolder 語法,可以設置系統或 .properties 属性,搭配 Spring EL,可設置運算式結果、其他 Bean 的屬性,搭配特定協定,可以設置文件或者是 URL 資源等。
最單純的就是注入某個值,指定值時一律使用字串指定,若實際上是個整數或者是浮點數,Spring 會自動依注入的對象型態自動剖析,若無法剖析,例如將 @Value("3.14")
標註在 int
的值域上,會發生 NumberFormatException
:
@Value("guest")
private String name;
@Value("9999")
private int id;
@Value("3.14")
private double pi;
要指定某個屬性,可以使用 @Value("${...}")
,例如:
@Value("${spring.profiles.active}")
private String ;
PlaceHolder 可以設定預設值,例如 @Value("${cc.openhome.user:caterpillar}")
的話,在沒有對應的 cc.openhome.user
時,就會使用 "caterpillar"
這個值。
Spring EL 是 Spring 提供的運算式語言(Expression Language),形式為 #{expr}
,可以搭配 @Value
使用,例如基本的運算、三元運算或者是結合 PlaceHolder 等:
@Value("#{1 + 2.4 * 3}")
private double a;
@Value("#{1 > 2 ? 'Yes' : 'No'}")
private String flag;
@Value("#{'${cc.openhome.workspace}' + '/data'}")
private String dir;
如果想要注入 Spring 管理的某 Bean 的屬性值,例如某個 Bean 實例 getFoo()
的值,可以如下:
@Value("#{beanName.foo}")
private String foo;
也可以進一步呼叫傳回值的方法,例如若 getFoo()
傳回 String
的話,想呼叫其 toUpperCase
:
@Value("#{beanName.foo.toUpperCase()}")
private String foo;
若 getFoo()
可能傳回 null
,為了避免 NullPointerException
,可以使用 ?
測試,只有在不是 null
的情況下,才會進一步呼叫指定的方法:
@Value("#{beanName.foo?.toUpperCase()}")
private String foo;
可以使用 #{T(....)}
指定某個類別,並進一步進行操作。指定時必須是類別全名,java.lang
下的類別可以指定類別全名或只指定類別名稱,例如:
@Value("#{T(java.lang.Math).PI}")
private double pi;
@Value("#{T(System).currentTimeMillis()}")
想要指定系統屬性的話,可以使用 #{systemProperties['propName']}
,例如:
@Value("#{systemProperties['os.name']}")
private String osName;
更多 Spring EL 的說明可以參考〈Spring Expression Language (SpEL)〉。
@Value
也可以注入資源,注入的資源型態是 org.springframework.core.io.Resource
的實作,實際型態依你設定的協定而定,例如::
@Value("classpath:jdbc.properties")
private Resource jdbc;
@Value("https://openhome.cc")
private Resource site;
在上例中,jdbc
實際上注入的會是 ClassPathResource
,而 site
會是 UrlResource
。