【Java】所以,到底什麼是依賴注入(Dependency Injection) ?

更新 發佈閱讀 7 分鐘

前言

你可能看過很多課程,每個都跟你說要寫出高內聚低耦合,少不了依賴注入的使用。又或者Spring Boot.NET等框架學習,最初幾個章節大多會介紹依賴注入,甚至許多資深前輩開口閉口總是一句: 不要自己new,讓框架幫你處理。

在真實專案裡,我們確實大量使用框架提供的 DI 特性(例如 Spring 的 @Autowired),但有時候在維護或理解程式時,還是會疑惑:不自己 new,功能到底要怎麼寫?

今天就來探討一下,到底什麼是依賴注入。

原始寫法

// 咖啡豆
class ArabicaBean {
public String getBean() {
return "阿拉比卡咖啡豆";
}
}

// 咖啡機自己 new 咖啡豆
class CoffeeMachine {
private CoffeeBean bean;

public CoffeeMachine() {
this.bean = new ArabicaBean(); // 直接 new
}

public void brew() {
System.out.println("沖煮 " + bean.getBean());
}
}

public class App {
public static void main(String[] args) {
CoffeeMachine machine = new CoffeeMachine();
machine.brew();
}
}
  1. 主要方法很單純,new建立一台咖啡機實例,呼叫煮咖啡。
  2. 咖啡機在建立實際的咖啡豆,也就是阿拉比卡咖啡豆,咖啡機擁有控制權。
  3. 如果要曼特寧豆,不好意思,請買別台機器,因為咖啡機寫死只能用阿拉比卡豆。

改成依賴注入

class ArabicaBean {
public String getBean() {
return "阿拉比卡咖啡豆";
}
}


// 咖啡機:不自己 new,外部給豆子
class CoffeeMachine {
private ArabicaBean bean;

public CoffeeMachine(ArabicaBean bean) { // 建構子注入
this.bean = bean;
}

public void brew() {
System.out.println("沖煮 " + bean.getBean());
}
}

public class App {
public static void main(String[] args) {
// 外部決定要用哪種豆子
ArabicaBean bean = new ArabicaBean();
CoffeeMachine machine = new CoffeeMachine(bean); // 注入依賴
machine.brew();
}
}
  1. 咖啡機不自己建立咖啡豆,建構子改由外部傳入豆子,控制權已移轉。
  2. 主要方法在使用上,改由先決定哪個咖啡豆,再把豆子丟給咖啡機。
  3. 如果要曼特寧豆,抱歉,機器還是只吃阿拉比卡豆。

加入抽象

當然,總不能一台機器只能煮單一種豆子吧? 可以加入抽象解決這個問題。

// 咖啡豆抽象
interface CoffeeBean {
String getBean();
}

// 具體的咖啡豆
class ArabicaBean implements CoffeeBean {
public String getBean() {
return "阿拉比卡咖啡豆";
}
}

class MandhelingBean implements CoffeeBean {
public String getBean() {
return "曼特寧咖啡豆";
}
}

// 咖啡機不自己 new,外部注入
class CoffeeMachine {
private CoffeeBean bean;

public CoffeeMachine(CoffeeBean bean) { // 建構子注入
this.bean = bean;
}

public void brew() {
System.out.println("沖煮 " + bean.getBean());
}
}

public class App {
public static void main(String[] args) {
// 外部決定要用哪種豆子
CoffeeBean bean = new MandhelingBean();
CoffeeMachine machine = new CoffeeMachine(bean); // 注入依賴
machine.brew();
}
}
  1. 主要方法決定要哪種咖啡豆,就new出實際咖啡豆丟給咖啡機
  2. 只要阿拉比卡跟曼特寧是咖啡豆,咖啡機就能運作

框架做了什麼?

透過上述例子可以發現一件事: 外部總得有個地方去new出物件,只不過更集中管理,而這個最髒的地方,正是框架幫我們處理的事情,包含物件的建立、生命週期控管、自動解析依賴並注入到需要的地方。

理解了這些,你就能更清楚框架在底層如何運作,也能在面對這些技術名詞時更從容地掌握它們的意義。


留言
avatar-img
Err500
14會員
83內容數
遇到的坑、解過的題、新知識的探索、舊時代的遺毒!? 工作後我發現,文件更新往往跟不上新需求的更迭,犯錯的歷史總是不斷重演。因此,我改變了方式,蒐集從程式上、系統上的每一次異常處理過程,好讓再次遇到相同的問題時能快速應變。此專題就是我的錯題本,期待日後不管在工作上或交流上遇到難題,都能輕鬆地應答:有什麼難的,我都踩過。
Err500的其他內容
2025/10/25
本文記錄了一個新專案的技術選型、架構設計與流程規劃的經驗,作者從中學習到技術決策的考量,以及如何在團隊中推動改變。
Thumbnail
2025/10/25
本文記錄了一個新專案的技術選型、架構設計與流程規劃的經驗,作者從中學習到技術決策的考量,以及如何在團隊中推動改變。
Thumbnail
2025/03/16
這篇文章說明如何使用Spring JDBC Template從資料庫取得資料,並將其輸出為CSV檔案。文中詳細介紹了系統架構、程式實作,以及測試結果,並討論了未來可能的擴展。
Thumbnail
2025/03/16
這篇文章說明如何使用Spring JDBC Template從資料庫取得資料,並將其輸出為CSV檔案。文中詳細介紹了系統架構、程式實作,以及測試結果,並討論了未來可能的擴展。
Thumbnail
2025/03/15
本文比較IntelliJ IDEA、VSCode和Eclipse三種Java開發工具的優缺點,針對不同使用者族群提供建議。IntelliJ IDEA適合初學者,VSCode輕量且具彈性,Eclipse則適合舊專案開發。
Thumbnail
2025/03/15
本文比較IntelliJ IDEA、VSCode和Eclipse三種Java開發工具的優缺點,針對不同使用者族群提供建議。IntelliJ IDEA適合初學者,VSCode輕量且具彈性,Eclipse則適合舊專案開發。
Thumbnail
看更多
你可能也想看
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
當你想升級設備、投放廣告,或是為了雙 11 提前備貨,卻發現現金流卡住時,除了等銀行、跟親友開口,其實還有一個常被忽略、卻很有力的選項。讓房子,成為你事業的贊助商——國峯厝好貸。
Thumbnail
當你想升級設備、投放廣告,或是為了雙 11 提前備貨,卻發現現金流卡住時,除了等銀行、跟親友開口,其實還有一個常被忽略、卻很有力的選項。讓房子,成為你事業的贊助商——國峯厝好貸。
Thumbnail
本屆 #JCConf 邀請到 許子謙 分享「用AI進行老舊java專案的現代化重構經驗談」 講題簡介: 介紹運用 AI 工具(如 GitHub Copilot)協助公司內部老舊 Java 專案的現代化重構。這些專案原本採用 Java 8,未使用任何框架,功能皆由開發人員實作,模組間以函式互相
Thumbnail
本屆 #JCConf 邀請到 許子謙 分享「用AI進行老舊java專案的現代化重構經驗談」 講題簡介: 介紹運用 AI 工具(如 GitHub Copilot)協助公司內部老舊 Java 專案的現代化重構。這些專案原本採用 Java 8,未使用任何框架,功能皆由開發人員實作,模組間以函式互相
Thumbnail
本屆 #JCConf 邀請到 Samson,陳冠緯 分享「用 Spring AI + OpenAPI 擴充 Agent 能力:讓你的 API 接上自然語言」 講題簡介: 想讓你的後端 API 能被 AI 自然語言驅動?本場分享將示範如何結合 Spring AI、OpenAPI Generat
Thumbnail
本屆 #JCConf 邀請到 Samson,陳冠緯 分享「用 Spring AI + OpenAPI 擴充 Agent 能力:讓你的 API 接上自然語言」 講題簡介: 想讓你的後端 API 能被 AI 自然語言驅動?本場分享將示範如何結合 Spring AI、OpenAPI Generat
Thumbnail
此章節旨在介紹Java程式語言中的各種資料型別,包括基本型別、引用型別、集合型別、陣列型別、字典型別等。它還講解了如何在Java中進行型別轉換和自定義型別,並提供了相關的程式碼示例。
Thumbnail
此章節旨在介紹Java程式語言中的各種資料型別,包括基本型別、引用型別、集合型別、陣列型別、字典型別等。它還講解了如何在Java中進行型別轉換和自定義型別,並提供了相關的程式碼示例。
Thumbnail
此章節旨在引導讀者如何建立Java開發環境,包括安裝JDK、使用命令行工具編寫和運行Java程式,以及如何在Visual Studio Code、IntelliJ IDEA和Eclipse等IDE中設置和使用Java環境。
Thumbnail
此章節旨在引導讀者如何建立Java開發環境,包括安裝JDK、使用命令行工具編寫和運行Java程式,以及如何在Visual Studio Code、IntelliJ IDEA和Eclipse等IDE中設置和使用Java環境。
Thumbnail
此章節旨在介紹Java的基本語法、註解和變數的使用。透過學習,讀者將了解Java程式的基本結構、程式進入點的定義、如何撰寫單行和多行註解,以及如何宣告和初始化變數。
Thumbnail
此章節旨在介紹Java的基本語法、註解和變數的使用。透過學習,讀者將了解Java程式的基本結構、程式進入點的定義、如何撰寫單行和多行註解,以及如何宣告和初始化變數。
Thumbnail
這篇文章的目的是對Java程式設計語言進行介紹,包括它的特性、應用範疇、主要使用者,以及相關的學習資源和常見的庫與框架。此外,它也提供了一些學習Java的渠道,以及與Java相關的其他知識。
Thumbnail
這篇文章的目的是對Java程式設計語言進行介紹,包括它的特性、應用範疇、主要使用者,以及相關的學習資源和常見的庫與框架。此外,它也提供了一些學習Java的渠道,以及與Java相關的其他知識。
Thumbnail
這幾年新出的語言都強打在少寫 code 和提高可讀性,更重要的是能更容易發展出 domain specific language,就這一點 Java 確實有點顯得疲態了。其實文中列的特性大多是一些語法糖衣,但對程式的可讀性和抽象度都能提昇不少,我覺得挺實用也很划算的。
Thumbnail
這幾年新出的語言都強打在少寫 code 和提高可讀性,更重要的是能更容易發展出 domain specific language,就這一點 Java 確實有點顯得疲態了。其實文中列的特性大多是一些語法糖衣,但對程式的可讀性和抽象度都能提昇不少,我覺得挺實用也很划算的。
Thumbnail
很明顯可以看到 parallelSort(T[], Comparator<T> 大概可以帶來 2.5 倍到接近 3 倍的效能增益 (和數量無關)。所以,結論是當需要處理大量資料的排序時,真的可以考慮使用 parallelSort(T[], Comparator<T>。
Thumbnail
很明顯可以看到 parallelSort(T[], Comparator<T> 大概可以帶來 2.5 倍到接近 3 倍的效能增益 (和數量無關)。所以,結論是當需要處理大量資料的排序時,真的可以考慮使用 parallelSort(T[], Comparator<T>。
Thumbnail
default methods 似乎也引起不小的討論,因為 default methods 加上可以實作多個介面,已經有點像 C++ 的多重繼承了,只差在沒辦法繼承成員變數而已,是好是壞就看怎麼使用了。我個人覺得還蠻方便的
Thumbnail
default methods 似乎也引起不小的討論,因為 default methods 加上可以實作多個介面,已經有點像 C++ 的多重繼承了,只差在沒辦法繼承成員變數而已,是好是壞就看怎麼使用了。我個人覺得還蠻方便的
Thumbnail
萬事起頭 這個簡單到不行的極度簡略步驟,卻是一切的基礎
Thumbnail
萬事起頭 這個簡單到不行的極度簡略步驟,卻是一切的基礎
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News