首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java 接口字段初始化為 null 卻能調用方法?依賴注入原理解析

     編輯:程式設計綜合問答

代碼現象

public ICommonDao commonDao = null;

public List getAllDbTableName() {
    return commonDao.getAllDbTableName(); // 運行時不報 NPE
}

核心原理:依賴注入

ICommonDao 是接口,commonDao 在聲明處為 null,但運行時容器(Spring、Guice、Dagger 等)會在 Bean 初始化階段,通過反射或字節碼增強將具體實現類(如 CommonDaoImpl)的實例注入到該字段。

典型流程

  1. 掃描:容器啟動掃描帶有 @Component/@Service 等註解的類。
  2. 實例化:創建 CommonDaoImpl 實例。
  3. 注入:發現目標類含 @Autowired 或 @Inject 的 ICommonDao commonDao 字段,將實例賦值。
  4. 代理:若開啟 AOP,可能注入的是 JDK 動態代理或 CGLIB 代理對象。

為什麼不直接 new 實現類?

  • 解耦:上層業務邏輯僅依賴接口,不關心具體實現,便於單元測試替換 Mock 對象。
  • 多實現切換:同一接口可有 MySQL、Oracle、Redis 等多種實現,通過配置文件或條件註解動態切換。
  • 生命週期管理:容器統一管理單例、原型、請求等作用域,避免手動管理導致內存洩漏。

常見誤區

「字段是 null 就不能調用」 —— 這是靜態視角。運行時容器已完成注入,實際引用指向真實對象。若在 main 方法或未托管容器的類中直接調用,確會拋 NPE。

最佳實踐

  • 優先使用 構造器注入(final 字段、不可變、易測試),而非字段注入。
  • 接口命名避免 I 前綴,現代風格直接用 CommonDao,實現類加 Impl 後綴。
  • 啟用 @RequiredArgsConstructor(onConstructor_ = @Autowired) (Lombok) 簡化構造器注入樣板代碼。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved