Spring EL(#{...})與屬性佔位符(${...})雖語法相似,但能力差異巨大。本文彙總 9 大高頻實戰場景,助你靈活駕馭配置與注入。
| 語法 | 用途 | 特性 |
|---|---|---|
${...} | 讀取 .properties/YAML 配置 | 單值解析,取最後匹配值 |
#{...} | SpEL 表達式 | 支援運算、方法調用、集合、正則、Bean 互調,取所有匹配值 |
${...})# application.properties
app.name=我的應用
@Value("${app.name}")
private String appName;
@Value("${app.desc:預設描述}") // 單引號包裹字串字面值
private String desc;
# 配置: app.tags=tag1,tag2,tag3
@Value("#{'${app.tags}'.split(',')}")
private List<String> tagList;
@Value("${env=='prod'?'生產環境':'測試環境'}")
private String envDesc;
// 也可直接用於方法參數
@GetMapping("/env")
public String env(@Value("${env=='prod'?'生產':'測試'}") String desc) { ... }
#{...})@Value("#{'12345' matches '\\d+'}") // true
private boolean isNumeric;
@Value("#{systemProperties['os.name']}") // Windows 10, Mac OS X 等
private String osName;
@Value("#{systemProperties['user.timezone']}")
private String timezone;
T(Type) 語法)@Value("#{T(java.lang.Math).random() * 100}")
private double randomVal; // 注意:啟動時只計算一次,非每次調用
// 自定義工具類
@Value("#{T(com.example.util.IdGenerator).nextId()}")
private long orderId;
@Value("classpath:templates/email/welcome.txt")
private Resource welcomeTpl;
@GetMapping("/welcome")
public String welcome() throws IOException {
return IOUtils.toString(welcomeTpl.getInputStream(), StandardCharsets.UTF_8);
}
提示:讀取資源內容推薦使用 org.apache.commons.io.IOUtils 或 FileCopyUtils。
@Component("configProvider")
public class ConfigProvider {
public String getActiveProfile() { return "production"; }
}
// 另一個 Bean 注入
@Value("#{configProvider.activeProfile}") // 呼叫 getter
// 或
@Value("#{configProvider.getActiveProfile()}")
private String activeProfile;
注意:被調用 Bean 建議明確指定 @Component("beanName"),避免預設命名衝突。
@Value("#{{'k1':'v1','k2':'v2'}}")
private Map<String,String> map;
@Value("#{'a,b,c'.split(',')}")
private List<String> list;
${...} 專注配置解析,#{...} 專注運算邏輯。@Configuration 類的 @Bean 方法中,保持 Controller/Service 簡潔。