」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > Spring Boot 中的依賴注入:幕後嚮導

Spring Boot 中的依賴注入:幕後嚮導

發佈於2024-11-09
瀏覽:639

Dependency Injection in Spring Boot: The Wizard Behind the Curtain

Spring Boot 中的依赖注入:幕后向导

是否曾经感觉 Spring Boot 是一个神奇的管家,不知怎的,它只是 知道 你需要什么,然后把它放在银盘上送给你?这基本上就是依赖注入 (DI)。您可能已经使用过 DI 一百次,却没有停下来思考:Spring 到底是如何知道注入什么以及何时注入?

如果这听起来像您,欢迎加入!我们将进行一次有趣的幕后之旅,了解 Spring Boot 的 DI 如何发挥其魔力,从它如何管理 bean、@Autowired 和 bean 生命周期(从诞生到销毁)开始。在本博客结束时,您将像专业人士一样展示您新发现的 DI 知识。


什么是依赖注入?为什么你应该关心?

通俗地说,依赖注入就像是让杂货送货上门,而不是自己出去买。它是将“注入”依赖项(bean)的责任委托给 Spring,这样您就不必手动创建对象或担心它们的生命周期。

假设您是一名厨师,经营着一个繁忙的厨房(您的应用程序)。你没有时间每次需要鸡蛋、牛奶和糖时都跑出去买。如果有人(比如 Spring)能够神奇地在您需要的时候准确地交付您需要的一切,那不是很棒吗?

这正是 Spring DI 所做的:它找到您需要的所有成分(bean)并将它们注入到您的代码中,而无需您费力。很整洁吧?


Spring Container 的魔力:您的私人管家

好吧,这就是奇迹发生的地方。当您使用 SpringApplication.run() 运行 Spring Boot 应用程序时,Spring 会引导 ApplicationContext - 将其视为您的管家的说明手册。它确切地知道要获取什么以及何时获取。

我们一步步分解:

  1. 容器初始化: 当你点击 SpringApplication.run() 时,Spring 容器(又名 ApplicationContext)就会启动。这就像打开虚拟餐厅的大门,一切准备就绪。

  2. Bean 创建: 容器会扫描您的代码以查找 @Component、@Service、@Repository 或 @Controller 等注释。其中每一个都成为一个 bean——一个由 Spring 管理的对象。将它们视为厨房中的基本成分:面粉、糖、鸡蛋等。

  3. BeanFactory 来救援: Spring Boot 使用 BeanFactory 来创建和管理这些 bean。该工厂确切地知道如何以及何时创建您的 Bean,确保它们在需要时可用。

  4. 依赖注入:一旦bean准备好了,Spring就会在你用@Autowired标记的地方注入它们。这就像咖啡师不仅会煮咖啡,还会将咖啡送到需要的地方。你甚至不需要考虑它——一切都会出现


@Autowired 如何工作?豆子大侦探福尔摩斯

啊,很好的 @Autowired 注释。有没有想过 Spring 如何神奇地知道在哪里注入依赖项?它有点像一个侦探,将您的需求与注册表中正确的 bean 相匹配。

其工作原理如下:

  • 类型匹配:当Spring看到@Autowired时,它会在容器中寻找相同类型的bean。想象一下,您订购了咖啡豆(一个 CoffeeService 类),Spring 会在其 Bean 存储库中查找并说:“啊,我已经有了这些!让我给你注射。”

  • 限定符: 但是如果您有多个相同类型的 bean 怎么办?在这种情况下,Spring 可能会崩溃并抛出“NoUniqueBeanDefinitionException”之类的异常。但别担心——你可以通过使用 @Qualifier 指定要注入哪个 bean 来让 Spring 平静下来:

@Autowired
@Qualifier("espressoBean")
private CoffeeService coffeeService;
  • 构造函数注入(最好的方法): 如今,构造函数注入是最酷的东西。它不仅使您的 Bean 不可变,而且还使测试变得轻而易举。操作方法如下:
public class CoffeeShop {

    private final CoffeeService coffeeService;

    @Autowired
    public CoffeeShop(CoffeeService coffeeService) {
        this.coffeeService = coffeeService;
    }
}

Spring 继续自动驾驶,将 bean 注入到构造函数中,瞧,一切顺利!


Spring Bean 的生命周期:从出生到退休派对

Spring Boot 中的 Bean 不仅仅是对象。他们拥有充实的生活、完整的起源故事、充实的职业生涯和最终的退休生活。让我们跟踪一下 bean 的生命周期:

  1. 实例化(诞生): 首先,Spring 创建 bean 的一个实例。这就像豆子的诞生一样。春天说:“给你,小家伙!”并将其传递到容器中。

  2. 依赖注入: 创建 bean 后,Spring 会用依赖项填充它(就像蛋糕配方中的成分)。这就是@Autowired 发挥作用的地方。您的 Bean 获得了正常工作所需的一切。

  3. 初始化后: 如果你有用@PostConstruct注释的方法,Spring会在注入依赖项后调用这些方法。这就像在豆子开始工作之前给它涂上一层新油漆。

  4. 准备行动: 现在你的豆子已经活过来了。它已经准备好迎接世界了!

  5. 预销毁(退休): 当应用程序关闭时,Spring 调用 @PreDestroy 方法让 bean 正常退出。这是 Bean 的退休聚会,它清理其资源。

  6. Bean 销毁: 最后,bean 被销毁。是时候安息了。

以下是如何在代码中跟踪这些生命周期事件:

@Component
public class CoffeeBean {

    @PostConstruct
    public void onStart() {
        System.out.println("Bean is ready to brew some coffee!");
    }

    @PreDestroy
    public void onEnd() {
        System.out.println("Bean is retiring. Goodbye, world!");
    }
}

Bean Scopes:魔法能持续多久?

并非所有豆类的预期寿命都相同。 Spring Boot 允许您为 beans 定义不同的范围——基本上是它们的寿命。最常见的两个是:

  • Singleton(默认): bean 只有一个实例,在整个应用程序中共享。这就像整个咖啡店都拥有一台浓缩咖啡机。

  • 原型: 每次需要时都会创建一个新的 bean 实例。想象一下,每个订单都有一台新鲜的浓缩咖啡机。它占用大量资源,但有时是必要的。

@Component
@Scope("prototype")
public class LatteMachine {
    // This bean is made fresh for every use
}

SpringApplication.run():DI 大师

好吧,让我们来谈谈使用 SpringApplication.run() 运行 Spring Boot 应用程序时会发生什么。这个方法是启动整个 DI 过程的大师。

  1. 启动应用程序上下文: Spring 启动 ApplicationContext,所有 bean 都位于其中。
  2. 扫描 Beans: Spring 扫描您的代码以查找 Bean 并注册它们。
  3. 注入依赖关系:一旦bean准备好,Spring就开始在使用@Autowired的地方注入它们。
  4. 启动应用程序:一切就绪后,应用程序就会上线。魔法完成。

现实生活中的类比:咖啡店里的 DI

将您的 Spring Boot 应用程序视为一家咖啡店。你是主人,豆子就是你的原料:咖啡、牛奶、糖等。你不用自己跑来跑去管理这些原料,而是有一个咖啡师(Spring 容器)来获取所有东西并将其准确地交付到它所在的位置需要。

您所要做的就是下订单(设置您的 @Autowired 字段),咖啡师会处理剩下的事情 — 为您的客户完美地冲泡一杯充满依赖的咖啡(应用程序)。


总结:DI 是你的超能力

归根结底,依赖注入使得 Spring Boot 成为如此强大的框架。它简化了您的生活,管理您的 Bean,并确保您的代码易于维护和扩展。

既然您已经窥视了幕后,您就拥有了许多开发人员认为理所当然的超能力。所以,继续吧——像现在的向导一样开始使用 DI。下次您看到@Autowired 时,您就会确切地知道幕后发生了什么。


希望这篇博客能让您对Spring Boot DI有更深入的了解,并给您留下微笑。现在去注入一些豆子并向你的朋友展示它是如何完成的!


对于一个有趣、信息丰富且易于理解的博客来说怎么样?如果您需要更多调整,请告诉我!

版本聲明 本文轉載於:https://dev.to/janisyed18/dependency-injection-in-spring-boot-the-wizard-behind-the-curtain-49n8?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 為什麼儘管有效代碼,為什麼在PHP中捕獲輸入?
    為什麼儘管有效代碼,為什麼在PHP中捕獲輸入?
    在php ;?>" method="post">The intention is to capture the input from the text box and display it when the submit button is clicked.但是,輸出...
    程式設計 發佈於2025-05-18
  • CSS強類型語言解析
    CSS強類型語言解析
    您可以通过其强度或弱输入的方式对编程语言进行分类的方式之一。在这里,“键入”意味着是否在编译时已知变量。一个例子是一个场景,将整数(1)添加到包含整数(“ 1”)的字符串: result = 1 "1";包含整数的字符串可能是由带有许多运动部件的复杂逻辑套件无意间生成的。它也可以是故意从单个真理...
    程式設計 發佈於2025-05-18
  • HTML格式標籤
    HTML格式標籤
    HTML 格式化元素 **HTML Formatting is a process of formatting text for better look and feel. HTML provides us ability to format text without us...
    程式設計 發佈於2025-05-18
  • Python不會對超範圍子串切片報錯的原因
    Python不會對超範圍子串切片報錯的原因
    在python中用索引切片範圍:二重性和空序列索引單個元素不同,該元素會引起錯誤,切片在序列的邊界之外沒有。 這種行為源於索引和切片之間的基本差異。索引一個序列,例如“示例” [3],返回一個項目。但是,切片序列(例如“示例” [3:4])返回項目的子序列。 索引不存在的元素時,例如“示例” [9...
    程式設計 發佈於2025-05-18
  • Python中何時用"try"而非"if"檢測變量值?
    Python中何時用"try"而非"if"檢測變量值?
    使用“ try“ vs.” if”來測試python 在python中的變量值,在某些情況下,您可能需要在處理之前檢查變量是否具有值。在使用“如果”或“ try”構建體之間決定。 “ if” constructs result = function() 如果結果: 對於結果: ...
    程式設計 發佈於2025-05-18
  • 如何從Python中的字符串中刪除表情符號:固定常見錯誤的初學者指南?
    如何從Python中的字符串中刪除表情符號:固定常見錯誤的初學者指南?
    從python import codecs import codecs import codecs 導入 text = codecs.decode('這狗\ u0001f602'.encode('utf-8'),'utf-8') 印刷(文字)#帶有...
    程式設計 發佈於2025-05-18
  • 在C#中如何高效重複字符串字符用於縮進?
    在C#中如何高效重複字符串字符用於縮進?
    在基於項目的深度下固定字符串時,重複一個字符串以進行凹痕,很方便有效地有一種有效的方法來返回字符串重複指定的次數的字符串。使用指定的次數。 constructor 這將返回字符串“ -----”。 字符串凹痕= new String(' - ',depth); console.W...
    程式設計 發佈於2025-05-18
  • 找到最大計數時,如何解決mySQL中的“組函數\”錯誤的“無效使用”?
    找到最大計數時,如何解決mySQL中的“組函數\”錯誤的“無效使用”?
    如何在mySQL中使用mySql 檢索最大計數,您可能會遇到一個問題,您可能會在嘗試使用以下命令:理解錯誤正確找到由名稱列分組的值的最大計數,請使用以下修改後的查詢: 計數(*)為c 來自EMP1 按名稱組 c desc訂購 限制1 查詢說明 select語句提取名稱列和每個名稱...
    程式設計 發佈於2025-05-18
  • 為什麼在我的Linux服務器上安裝Archive_Zip後,我找不到“ class \” class \'ziparchive \'錯誤?
    為什麼在我的Linux服務器上安裝Archive_Zip後,我找不到“ class \” class \'ziparchive \'錯誤?
    Class 'ZipArchive' Not Found Error While Installing Archive_Zip on Linux ServerSymptom:When attempting to run a script that utilizes the ZipAr...
    程式設計 發佈於2025-05-18
  • 如何從PHP中的數組中提取隨機元素?
    如何從PHP中的數組中提取隨機元素?
    從陣列中的隨機選擇,可以輕鬆從數組中獲取隨機項目。考慮以下數組:; 從此數組中檢索一個隨機項目,利用array_rand( array_rand()函數從數組返回一個隨機鍵。通過將$項目數組索引使用此鍵,我們可以從數組中訪問一個隨機元素。這種方法為選擇隨機項目提供了一種直接且可靠的方法。
    程式設計 發佈於2025-05-18
  • 如何在鼠標單擊時編程選擇DIV中的所有文本?
    如何在鼠標單擊時編程選擇DIV中的所有文本?
    在鼠標上選擇div文本單擊帶有文本內容,用戶如何使用單個鼠標單擊單擊div中的整個文本?這允許用戶輕鬆拖放所選的文本或直接複製它。 在單個鼠標上單擊的div元素中選擇文本,您可以使用以下Javascript函數: function selecttext(canduterid){ if(d...
    程式設計 發佈於2025-05-18
  • MySQL中如何高效地根據兩個條件INSERT或UPDATE行?
    MySQL中如何高效地根據兩個條件INSERT或UPDATE行?
    在兩個條件下插入或更新或更新 solution:的答案在於mysql的插入中...在重複鍵更新語法上。如果不存在匹配行或更新現有行,則此功能強大的功能可以通過插入新行來進行有效的數據操作。如果違反了唯一的密鑰約束。 實現所需的行為,該表必須具有唯一的鍵定義(在這種情況下為'名稱'...
    程式設計 發佈於2025-05-18
  • 為什麼我的CSS背景圖像出現?
    為什麼我的CSS背景圖像出現?
    故障排除:CSS背景圖像未出現 ,您的背景圖像儘管遵循教程說明,但您的背景圖像仍未加載。圖像和样式表位於相同的目錄中,但背景仍然是空白的白色帆布。 而不是不棄用的,您已經使用了CSS樣式: bockent {背景:封閉圖像文件名:背景圖:url(nickcage.jpg); 如果您的html,cs...
    程式設計 發佈於2025-05-18
  • eval()vs. ast.literal_eval():對於用戶輸入,哪個Python函數更安全?
    eval()vs. ast.literal_eval():對於用戶輸入,哪個Python函數更安全?
    稱量()和ast.literal_eval()中的Python Security 在使用用戶輸入時,必須優先確保安全性。強大的Python功能Eval()通常是作為潛在解決方案而出現的,但擔心其潛在風險。本文深入研究了eval()和ast.literal_eval()之間的差異,突出顯示其安全性含義...
    程式設計 發佈於2025-05-18
  • 如何在Java中正確顯示“ DD/MM/YYYY HH:MM:SS.SS”格式的當前日期和時間?
    如何在Java中正確顯示“ DD/MM/YYYY HH:MM:SS.SS”格式的當前日期和時間?
    如何在“ dd/mm/yyyy hh:mm:mm:ss.ss”格式“ gormat 解決方案: args)拋出異常{ 日曆cal = calendar.getInstance(); SimpleDateFormat SDF =新的SimpleDateFormat(“...
    程式設計 發佈於2025-05-18

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3