在 Spring 開發中,@Value 是注入外部配置屬性的常用注解。本文將深入對比其兩種主要表達式形式——#{...} (SpEL) 與 ${...} (Placeholder),並通過具體 XML 配置示例,闡明底層機制差異與適用場景,幫助開發者避免常見配置陷阱。
| 語法 | 表達式類型 | 典型寫法 | 依賴組件 |
|---|---|---|---|
@Value("#{configProperties['key']}") | Spring Expression Language (SpEL) | 引用 Bean ID + Map 鍵 | PropertiesFactoryBean 生成的 Properties 對象 |
@Value("${key}") | Property Placeholder | 直接引用鍵名 | PropertyPlaceholderConfigurer 或 PreferencesPlaceholderConfigurer |
#{...})此方式需顯式定義一個 PropertiesFactoryBean Bean,將屬性文件加載為 java.util.Properties 對象,再通過 SpEL 從中取值。
<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:/config/t1.properties</value>
</list>
</property>
</bean>
Java 代碼中:
@Value("#{configProperties['t1.msgname']}")
private String msgName;
特點:
configProperties),IDE 可導航,重構安全。${...} 占位符時。${...})此方式依賴 PropertyPlaceholderConfigurer (或其子類) 在 Bean 定義階段解析 ${...} 佔位符,將屬性值直接替換到 Bean 定義中。
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="configProperties"/>
</bean>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="config/t1.properties"/>
</bean>
Java 代碼中:
@Value("${t1.msgname}")
private String msgName;
特點:
PropertyPlaceholderConfigurer 僅處理 XML 中的佔位符,若需在註解屬性值中使用,需確保 <context:property-placeholder/> 或相應 Bean 已加載。${...} 配合 @PropertySource (Spring 3.1+);需動態計算或引用 Bean 時用 #{...}。優先使用 @PropertySource + Environment 或 @ConfigurationProperties 實現類型安全綁定,減少硬編碼鍵名:
@Configuration
@PropertySource("classpath:/config/t1.properties")
public class AppConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
// 注入單個值
@Value("${t1.msgname}") String msgName;
// 或綁定到 POJO (推薦)
@Component
@ConfigurationProperties(prefix = "t1")
public class T1Properties {
private String msgname;
// getter/setter
}
這樣既保持了配置集中管理,又獲得了編譯期類型檢查與 IDE 支持,是當前企業級項目的主流做法。