Spring 的依賴注入(DI)機制基於 Setter 方法 或 建構子,這些都是實例方法,屬於物件層級。而 static 變數屬於類層級,在類載入時初始化,不屬於任何具體實例。因此,Spring 無法透過標準的 Setter 注入為靜態欄位賦值。
@Autowired
private static JdbcTemplate jdbcTemplate; // 編譯通過,但運行時為 null
雖然編譯不報錯,但在調用 jdbcTemplate.query() 時會拋出 NullPointerException。
核心原則:提供非靜態的 Setter 方法,內部賦值給靜態欄位。
public class JdbcUtil {
private static JdbcTemplate jdbcTemplate; // 靜態欄位
// 必須是非靜態 Setter,Spring 才能調用
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
JdbcUtil.jdbcTemplate = jdbcTemplate; // 賦值給靜態欄位
}
public static JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public static void executeQuery(String sql) {
jdbcTemplate.query(sql, ...); // 靜態方法中使用
}
}
<bean id="jdbcUtil" class="com.example.JdbcUtil">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
static 修飾符,否則 Spring 容器無法識別為屬性注入點。private,對外提供靜態 Getter。若不想暴露 Setter,可在實例 Bean 中初始化靜態欄位:
@Component
public class JdbcInitializer {
@Autowired
private JdbcTemplate jdbcTemplate;
@PostConstruct
public void init() {
JdbcUtil.jdbcTemplate = this.jdbcTemplate;
}
}
此法優點:封裝性更好,靜態欄位完全隱藏;缺點:需確保初始化順序(可用 @DependsOn 控制)。
Spring 不直接支援靜態欄位注入,但透過非靜態 Setter 間接賦值或 @PostConstruct 回調,即可優雅解決。切記:Setter 必須是實例方法,這是 Spring DI 機制的核心限制。