springboot ioc 控制反轉入門與實戰

Spring Boot3 IOC 項目地址

https://gitee.com/supervol/loong-springboot-study

(記得給個start,感謝)

IOC 概述

????????在 Spring Boot 3 中,IOC(Inversion of Control,控制反轉)是核心思想之一,它徹底改變了傳統 Java 開發中對象創建和依賴管理的方式,極大地降低了代碼耦合度,提升了系統的可維護性和擴展性。

IOC 核心概念

????????IOC 的本質是將對象的創建權、依賴關系的管理交給 Spring 容器,而非由開發者在代碼中手動 new 對象或維護依賴。這種 "反轉" 體現在:

  • 傳統開發:開發者主動控制對象創建(如UserService service = new UserService())和依賴注入(如service.setDao(new UserDao()))。
  • IOC 模式:Spring 容器負責創建對象(Bean),并根據配置自動將依賴對象 "注入" 到目標對象中,開發者只需聲明 "需要什么",無需關心 "如何獲取"。

IOC 與 DI 的關系

????????DI(Dependency Injection,依賴注入)是 IOC 的具體實現方式

  • IOC 是思想:強調 "反轉控制"(將對象管理權交給容器)。
  • DI 是手段:容器通過構造器、setter 方法等方式,將依賴對象 "注入" 到目標對象中,完成依賴關系綁定。

IOC 示例

????????請參考項目地址中 springboot-ioc/springboot-ioc-demo 模塊代碼。

IOC 使用

????????Spring Boot 3 基于 Spring Framework 6,簡化了 IOC 容器的配置(無需 XML,全注解驅動),核心步驟如下:

定義 Bean

????????讓容器管理對象,Spring 通過注解識別需要管理的對象(Bean),常用注解:

  • @Component:通用注解,標識一個類為 Spring 管理的 Bean(適用于普通組件)。
  • @Service:標注業務邏輯層(Service)的 Bean(語義化注解,本質是@Component)。
  • @Controller:標注控制層(MVC 中的 Controller)的 Bean。
  • @Repository:標注數據訪問層(DAO)的 Bean,還會自動處理數據庫操作異常。

?示例:定義 Service 層 Bean

// 業務邏輯層,@Service標識為Spring管理的Bean
@Service
public class UserService {// 后續通過DI注入依賴private final UserDao userDao;// 構造器注入(推薦)public UserService(UserDao userDao) {this.userDao = userDao;}public String getUserInfo() {return userDao.queryUser();}
}

示例:定義 DAO 層 Bean

// 數據訪問層,@Repository標識為Spring管理的Bean
@Repository
public class UserDao {public String queryUser() {return "用戶信息:張三";}
}

依賴注入(DI)

????????容器自動注入依賴,Spring 提供多種注入方式,推薦構造器注入(更符合單一職責,且避免空指針問題)。

(1)構造器注入(推薦)
通過類的構造方法,容器自動傳入依賴的 Bean(如上面UserService中注入UserDao)。

(2)Setter 方法注入
通過 setter 方法注入依賴,需配合@Autowired注解:

@Service
public class UserService {private UserDao userDao;// Setter注入@Autowiredpublic void setUserDao(UserDao userDao) {this.userDao = userDao;}
}

(3)字段注入(不推薦)
直接在字段上使用@Autowired注入,缺點是無法通過構造器保證依賴非空,且不利于單元測試:

@Service
public class UserService {// 字段注入(不推薦)@Autowiredprivate UserDao userDao;
}

啟動容器并使用 Bean

????????Spring Boot 通過@SpringBootApplication注解啟動容器,該注解包含:

  • @ComponentScan:自動掃描當前包及子包下的@Component(含@Service@Controller等)注解類,將其注冊為 Bean。

示例:啟動類與使用 Bean

// 啟動類,@SpringBootApplication標識Spring Boot應用入口
@SpringBootApplication
public class IocDemoApplication {public static void main(String[] args) {// 啟動Spring容器,返回ApplicationContext(容器上下文)ApplicationContext context = SpringApplication.run(IocDemoApplication.class, args);// 從容器中獲取UserService BeanUserService userService = context.getBean(UserService.class);// 調用Bean的方法(依賴已由容器自動注入)System.out.println(userService.getUserInfo()); // 輸出:用戶信息:張三}
}

自定義 Bean

????????非 @Component 注解類,如果需要將第三方類(如RedisTemplate)或未加@Component的類注冊為 Bean,可通過@Configuration+@Bean實現:

// 配置類,@Configuration標識為配置類
@Configuration
public class CustomConfig {// @Bean:將方法返回值注冊為Spring容器中的Bean,默認名稱為方法名@Beanpublic RedisUtil redisUtil() {return new RedisUtil(); // 假設RedisUtil是第三方工具類}
}// 使用自定義Bean
@Service
public class OrderService {private final RedisUtil redisUtil;// 注入自定義的RedisUtil Beanpublic OrderService(RedisUtil redisUtil) {this.redisUtil = redisUtil;}
}

Bean 的作用域

????????默認情況下,Spring 容器中的 Bean 是單例(singleton)(整個容器中只有一個實例)。可通過@Scope指定其他作用域:

  • @Scope("prototype"):多例,每次獲取 Bean 時創建新實例。
  • @Scope("request"):Web 環境中,每個請求對應一個實例。
  • @Scope("session"):Web 環境中,每個會話對應一個實例。

示例:多例 Bean

@Service
@Scope("prototype") // 多例模式
public class CartService {// ...
}

IOC 的優勢

  1. 解耦:對象創建與依賴管理交給容器,避免硬編碼依賴(如new UserService(new UserDao()))。
  2. 可維護性:集中管理 Bean 的生命周期和依賴,修改依賴只需調整配置。
  3. 可測試性:便于替換依賴(如測試時用 Mock 對象替換真實 DAO)。
  4. 靈活性:通過作用域、懶加載等配置,靈活控制 Bean 的創建時機和生命周期。

總結

????????Spring Boot 3 的 IOC 通過注解驅動簡化了 Bean 的定義和依賴管理,核心是 "將控制權交給容器"。實際開發中,推薦使用@Service@Repository等語義化注解定義 Bean,通過構造器注入管理依賴,配合@Configuration+@Bean處理自定義 Bean,充分發揮 IOC 的解耦優勢。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/97755.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/97755.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/97755.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LangGraph 重要注意事項和常見問題

01. 數據狀態與歸納函數在前面的課時中,我們說過在 LangGraph 中 節點 在默認情況下返回的字典數據會將原始數據覆蓋,例如下面的代碼最終返回結果是 {"messages": [4]} 而不是 [1,2,3,4],如下class MyState(TypedDict):messages: l…

避坑指南!解決Navicat運行SQL成功但沒有表的問題

在運行轉儲的SQL文件時,成功運行,試了很多辦法都不顯示出表。原因:當從一個高版本的 MySQL 數據庫導入數據到低版本的 MySQL 數據庫時,可能會遇到兼容性問題。因為高版本的 MySQL 可能支持 utf8mb4_0900_ai_ci,而低版本…

在 Elasticsearch 中使用用戶行為分析:使用 UBI 和 search-ui 創建一個應用程序

作者:來自 Elastic Eduard Martin 及 Alexander Dvila 通過一個實際示例學習如何在 Elasticsearch 中使用 UBI。我們將創建一個在搜索和點擊結果時生成 UBI 事件的應用程序。 想要獲得 Elastic 認證嗎?看看下一次 Elasticsearch Engineer 培訓什么時候開…

SpringBoot3中使用Caffeine緩存組件

SpringBoot3已經把EhCache從框架中刪除了&#xff0c;SpringBoot3默認的緩存組件為Caffeine&#xff0c;那么我們在SpringBoot3中如何去使用它了&#xff1f; 1.添加依賴 <dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>ca…

正則表達式與grep文本過濾詳解

文章目錄前言一、正則表達式概述1.1 定義1.2 主要用途1.3 Linux 中的正則表達式分類1.3.1 基礎正則表達式&#xff08;BRE&#xff09;1.3.2 擴展正則表達式&#xff08;ERE&#xff09;二、正則表達式的基本組成2.1 普通字符2.2 元字符2.2.1 基本元字符2.2.2 重復次數相關2.2.…

Dify 集成 Milvus 配置指南

&#x1f9e9; Dify 集成 Milvus 配置指南 &#x1f527; 詳細配置步驟 1. 環境準備與克隆倉庫 首先確保你的系統已安裝 Git、Docker 和 Docker Compose。然后克隆 Dify 的代碼倉庫&#xff1a; git clone https://github.com/langgenius/dify.git cd dify/docker2. 配置環境變…

為不平,不止于此

口碑可以成就一個人&#xff0c;也可以毀掉一個人&#xff0c; 所以我們選擇用實力去創造兩種無聲的口碑。 要么讓期待的你張口而呼&#xff0c; 要么讓挑剔的你啞口無言。瑪哈特科技創始人 #為不平&#xff0c;不止于此#

0902 C++類的匿名對象

Part 1.梳理思維導圖一.匿名對象1.概念沒有對象名的類對象2.格式類名();3.作用1.給有名對象初始化2.給對象數組初始化3.作為函數的參數傳遞給形參4.例子#include <iostream>using namespace std;class Dog {friend void Dogfriend(Dog &b); private:string name;int …

在 PySpark 中解鎖窗口函數的力量,實現高級數據轉換

本篇文章Mastering PySpark Window Functions: A Practical Guide to Time-Based Analytics適合數據分析和工程師入門了解PySpark的窗口函數。文章的亮點在于詳細介紹了窗口函數的基本概念及其在銷售數據分析中的實際應用&#xff0c;幫助讀者理解如何進行復雜的數據計算而無需…

從理念到實踐:三層解耦架構與“無系統”論

在上一篇中&#xff0c;我們揭示了“五層雙閉環”治理模型如何像骨骼一樣&#xff0c;為數字化轉型提供支撐和定型。但再宏偉的藍圖也需要堅實的施工來實現。今天&#xff0c;我們將深入最具體的實施層面&#xff0c;將“業務重塑”和“以人為本”的理念&#xff0c;轉化為可落…

詳細介紹Linux 內存管理struct page數據結構中的_count和_mapcount有什么區別?

在Linux內核的struct page中&#xff0c;_count&#xff08;或_refcount&#xff09;和_mapcount是兩個關鍵的引用計數成員&#xff0c;它們各自承擔不同的職責。以下是深度解析和代碼案例&#xff1a;1. _count vs _mapcount 區別詳解_count&#xff08;或_refcount&#xff0…

面陣 vs 線陣相機:怎么選不踩坑?選型公式直接套用

面陣vs線陣相機&#xff1a;怎么選不踩坑&#xff1f;選型公式直接套用&#x1f3af;面陣vs線陣相機怎么選不踩坑&#xff1f;&#x1f3af;一、面陣相機&#xff1a;工業檢測的“萬能選手”&#xff0c;拍全圖靠它&#x1f3af;二、線陣相機&#xff1a;大視野/高精度的“專屬…

Spring Security 如何使用@PreAuthorize注解

&#x1f9f1; 第一步&#xff1a;環境準備? 1. 創建數據庫&#xff08;MySQL&#xff09;-- 創建數據庫&#xff0c;使用 utf8mb4 字符集支持 emoji 和多語言 CREATE DATABASE security_demo CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;-- 使用該數據庫 USE security…

JVM中產生OOM(內存溢出)的8種典型情況及解決方案

Java中的OutOfMemoryError&#xff08;OOM&#xff09;是當JVM內存不足時拋出的錯誤。本文將全面剖析JVM中產生OOM的各種情況&#xff0c;包括堆內存溢出、方法區溢出、棧溢出等&#xff0c;并提供詳細的診斷方法和解決方案。 一、OOM基礎概念 1.1 OOM錯誤類型 Java中的OOM是…

【IEEE出版、EI檢索、往屆會后3個月檢索】第四屆信號處理、計算機網絡與通信國際學術會議(SPCNC 2025)

第四屆信號處理、計算機網絡與通信國際學術會議&#xff08;SPCNC 2025&#xff09;將于2025年12月5-7日于中國武漢召開&#xff08;線上同步&#xff09;。為本次會議旨在齊聚海內外信號處理、計算機網絡與通信等計算機領域的專家學者&#xff0c;為相關領域研究和從業人員提供…

Spring boot注解介紹

1. Spring 核心注解Spring Boot 是基于 Spring 框架的&#xff0c;所以核心注解依然適用。? 常見核心注解Component表示一個通用組件&#xff0c;Spring 會自動掃描并注入到容器中。Component public class MyComponent {public void sayHello() {System.out.println("He…

撤銷回退 情況?:已經 add ,但沒有 commit

撤銷回退 情況?&#xff1a;已經 add &#xff0c;但沒有 commit add 后還是保存到了暫存區呢&#xff1f;怎么撤銷呢&#xff1f; 1 # 向ReadMe中新增??代碼 2 hyb139-159-150-152:~/gitcode$ vim ReadMe 3 hyb139-159-150-152:~/gitcode$ cat ReadMe 4 hello bit 5 hell…

【Linux筆記】命令行與vim基礎

一、Linux命令行基礎 1. 基本語法命令空格參數&#xff08;可寫可不寫&#xff09;空格文件&#xff0c;文件夾&#xff08;可寫可不寫&#xff09;ls列出文件夾中的內容/opt 根目錄下的opt文件夾ls-a all顯示出所有文件以及隱藏文件/optls-a如果不寫則輸出一個點&#xff0c;當…

Redis 的整數集合:像分類收納盒一樣的整數專屬存儲

目錄 一、先懂定位&#xff1a;為什么需要整數集合&#xff1f;&#xff08;銜接哈希表&#xff09; 二、整數集合的結構&#xff1a;像 “貼了規格標簽的收納盒” 1. encoding&#xff1a;收納盒的 “規格標簽”&#xff08;核心&#xff1a;決定格子大小&#xff09; 2. …

Linux 進程狀態 — 僵尸進程

&#x1f381;個人主頁&#xff1a;工藤新一 &#x1f50d;系列專欄&#xff1a;C面向對象&#xff08;類和對象篇&#xff09; &#x1f31f;心中的天空之城&#xff0c;終會照亮我前方的路 &#x1f389;歡迎大家點贊&#x1f44d;評論&#x1f4dd;收藏?文章 文章目錄進…