在 Spring 框架中,直接對 static 靜態字段使用 @Autowired 或 @Resource 註解是無效的——Spring 只會對實例字段進行依賴注入。若業務場景確需在靜態方法或靜態上下文中使用 Spring 管理的 Bean,可通過 @PostConstruct 生命周期回調將實例引用賦值給靜態字段來實現。
@Resource
private static ITecharchService techarchService; // 注入為 null,Spring 不支持直接注入靜態字段
@Component // 必須是 Spring 組件才能觸發 @PostConstruct
public class DDUtils {
@Resource
private ITecharchService techarchService; // 1. 先注入到實例字段
private static DDUtils instance; // 2. 持有當前實例的靜態引用
@PostConstruct
public void init() {
instance = this; // 3. 初始化時將 this 賦給靜態變量
instance.techarchService = this.techarchService; // 4. 同步注入的 Bean 到靜態字段
}
// 靜態業務方法中直接調用靜態 service
public static void getA() {
instance.techarchService.getA();
}
}
DDUtils Bean,執行字段注入(techarchService)。@PostConstruct 標註的 init() 方法。init() 中將實例引用(this)賦值給靜態變量 instance,並將已注入的服務同步到靜態字段 techarchService。instance.techarchService 訪問服務實例。instance 暴露為 public static,需考慮多線程環境下的可見性(可加 volatile)。DisposableBean 或使用 @PreDestroy 清空靜態引用,防止內存洩漏。| 方案 | 優點 | 缺點 |
|---|---|---|
| @PostConstruct 中轉(本文方案) | 代碼改動小,符合 Spring 生命周期,無反射依賴 | 引入靜態狀態,測試稍繁瑣 |
| ApplicationContextAware + 靜態工具類 | 通用性強,可在任何靜態處獲取 Bean | 增加耦合,屬於 Service Locator 反模式 |
| @Autowired 設置方法(非靜態 setter 注入靜態字段) | 語法直觀 | Spring 不支持對靜態 setter 注入,無效 |
掌握此技巧,可在不破壞 Spring 依賴管理原則的前提下,優雅解決靜態上下文調用 Bean 的需求。