Spring兩個核心IoCDI(二)

DI(依賴注入)就是從IoC容器中獲取對象并賦值給某個屬性,這就是依賴注入的過程。

關于依賴注入有3種方式:

1、屬性注入

2、構造方法注入

3、setter注入

目錄

1、屬性注入

2、 構造方法注入

3、Setter方法注入

4、3種注入方式優缺點分析

屬性注入

構造方法注入:

Setter注入

5、@Autowired存在的問題以及解決方法

面試題

3種注入方式優缺點

@Autowired與@Resource的區別:

@Autowired的裝配順序


1、屬性注入

@Service
public class UserService {public void doService(){System.out.println("UserService.doService");}
}
@ResponseBody
@Controller
public class UserController {@Autowiredprivate UserService userService;public void sayHi() {userService.doService();System.out.println("UserController.sayHi");}@RequestMapping("/hello")public String hello(){return "hello";}
}
@SpringBootApplication
public class SpringIoCDemoApplication {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringIoCDemoApplication.class, args);UserController bean = context.getBean(UserController.class);bean.sayHi();
}
}

通過@Autowired注解,spring就會從容器中取出UserService對象賦值給userService屬性,如果不加這個注解,就會在userService.doService()這里報空指針異常。

ApplicationContext的對象也在spring IoC容器中,我們也能通過?@Autowired拿到它的對象,

?@Autowired
? ? private ApplicationContext context;然后用context再去獲取別的Bean對象。

但是我們一般不這樣用。

2、 構造方法注入

@Service
public class UserService {public void doService(){System.out.println("UserService.doService");}
}
@Controller
public class UserController2 {private UserService userService;public UserController2(UserService userService){this.userService = userService;}public void sayHi() {userService.doService();System.out.println("UserController.sayHi");}
}
@SpringBootApplication
public class SpringIoCDemoApplication {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringIoCDemoApplication.class, args);UserController2  uc = context.getBean(UserController2.class);uc.sayHi();
}
}

spring在創建UserController2對象的時候,因為這里只提供了一個需要UserService對象參數的構造方法,所以容器就會把UserService對象注入給this.userSercice屬性,因此uc.sayHi()能成功運行。

但是為了標準化一般建議把無參的構造方法也寫上,

@Controller
public class UserController2 {private UserService userService;public UserController2() {}public UserController2(UserService userService){this.userService = userService;}public void sayHi() {userService.doService();System.out.println("UserController.sayHi");}
}

此時再運行起來就會報錯,

因為spring在創建UserController2對象的時候有無參的構造方法就是用了無參的構造方法,所以就沒有給userService屬性賦值,因此userService.doService()這行會報空指針異常。

為了讓spring創建UserController2對象使用有UserService參數的構造方法,我們需要使用@Autowired注解

import com.bit.springiocdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class UserController2 {private UserService userService;public UserController2() {}@Autowiredpublic UserController2(UserService userService){this.userService = userService;}public void sayHi() {userService.doService();System.out.println("UserController.sayHi");}
}

所以只有一個構造方法時,@Autowired可以省略;有多個構造方法時需要通過添加@Autowired來指定spring用哪一個來創建對象。

3、Setter方法注入

import com.bit.springiocdemo.config.UserConfig;
import com.bit.springiocdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class UserController3 {private UserService userService;private UserConfig userConfig;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}@Autowiredpublic void setUserConfig(UserConfig userConfig) {this.userConfig = userConfig;}public void sayHi() {userService.doService();userConfig.doConfig();System.out.println("UserController.sayHi");}
}
@SpringBootApplication
public class SpringIoCDemoApplication {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringIoCDemoApplication.class, args);UserController3 uc3 = context.getBean(UserController3.class);uc3.sayHi();
}
}

通過setter方法來為屬性賦值,需要給setter方法添加@Autowired屬性,否則在sayHi()方法中就會報快指針異常。

4、3種注入方式優缺點分析

屬性注入

簡潔方便,但是只能用于IoC容器,并且不能注入一個Final修飾的屬性。

fianl修飾的屬性要么要初始化,要么通過構造方法進行賦值。

構造方法注入:

優點:

  • 可以注入final修飾的屬性,就是在構造方法中進行賦值
  • 注入的對象不會被修改
  • 依賴對象在使用前一定會被完全初始化的,因為依賴是在類的構造方法中注入的,而構造方法是在類加載時就會執行的
  • 通用性好,構造方法是jdk支持的,換任何框架都是適用的

缺點:注入多個對象比較麻煩

Setter注入

優點:方便在類實例話之后,還能對該對象進行配置或者注入

@Controller
public class UserController3 {private UserService userService;private UserConfig userConfig;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}@Autowiredpublic void setUserConfig(UserConfig userConfig) {this.userConfig = userConfig;}public void sayHi() {userService.doService();userConfig.doConfig();System.out.println("UserController.sayHi");}
}

就這個代碼來說,就是在UserController3實例化好之后,還能通過主動調用setter方法來給屬性賦值,更換注入的對象,所以這也是一個缺點

缺點:

  • 注入對象可能會被改變,因為setter可能多次調用,就有被修改的風險
  • 不能注入一個final修飾的屬性

當前Spring官方更推薦構造方法注入方式,程序員更推薦屬性注入方式。

5、@Autowired存在的問題以及解決方法

當一個類型有多個Bean時,使用@Autowired就會報錯

@AllArgsConstructor
@Data
public class UserInfo {private Integer id;private String name;private Integer age;
}
@Configuration
public class UserInfoConfig {@Bean(name = {"user1","lisi"})public UserInfo user1() {UserInfo userInfo = new UserInfo(1,"lisi",15);return userInfo;}@Beanpublic UserInfo user2() {UserInfo userInfo = new UserInfo(2,"kiku",31);return userInfo;}
}

從這里可以看到UserInfo類型在IoC容器中存了兩個對象,一個是通過user1()創建的,一個是user2()創建的

@Controller
public class UserController {@Autowiredprivate  UserService userService;@Autowiredprivate UserInfo userInfo;public void sayHi() {userService.doService();System.out.println(userInfo);System.out.println("UserController.sayHi");}
}

所以這里通過添加@Autowired給userInfo屬性注入對象時,不知道該使用容器中的哪一個來進行注入

@SpringBootApplication
public class SpringIoCDemoApplication {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringIoCDemoApplication.class, args);UserController bean = context.getBean(UserController.class);bean.sayHi();
}
}

報錯信息以及建議:

建議中有兩種解決方式,

一種是通過添加@Primary來選擇一個Bean對象作為主要選擇的、默認的,比如:

@Primary
@Bean(name = {"user1","lisi"})
public UserInfo user1() {UserInfo userInfo = new UserInfo(1,"lisi",15);return userInfo;
}

這樣就會選擇user1()創建的對象來注入。

另一種是通過@Qualifier來指定要注入的對象是誰。

@Controller
public class UserController {@Autowiredprivate  UserService userService;@Autowired@Qualifier("user2")private UserInfo userInfo;public void sayHi() {userService.doService();System.out.println(userInfo);System.out.println("UserController.sayHi");}
}

當兩個同時@Primary和@Qualifier都存在時,會使用@Qualifier()指定的,而不是默認的。

另外@Qualifier除了可以加在屬性上,還可以加在參數上:

  @Autowiredpublic UserController2(UserService userService, UserConfig userConfig,@Qualifier("user1") UserInfo userInfo) {this.userService = userService;this.userConfig = userConfig;this.userInfo = userInfo;}

除了spring建議的這兩種,我們還可以通過@Resource來解決:

//    @Autowired
//    @Qualifier("user2")@Resource(name = "user2")private UserInfo userInfo;

@Resource作用上就等于@Autowired+@Qualifier,

這個注解是jakarta提供的。

面試題

3種注入方式優缺點

@Autowired與@Resource的區別:

1、來源不同,@Autowired是spring框架提供的注解,@Resource是jdk提供的注解。

2、@Autowired是按照類型注入的(如果該類型只有一個Bean,直接注入;如果該類型有多個bean,就按屬性名稱注入,但是@Autowired不能指定bean的名稱來注入),

@Resource是按照名稱注入的

@Autowired的裝配順序

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

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

相關文章

廣東省省考備考(第八十三天8.21)——言語、判斷推理(強化訓練)

言語理解與表達 錯題解析 文段開篇介紹足夠的執法權限對于基層治理高效運行的重要性,接著從兩方面進行論證,介紹權限不足和權限過度下放對基層治理的負面影響,最后通過“因此”進行總結,強調一方面要完善執法目錄動態調整機制和制…

字符串與算法題詳解:最長回文子串、IP 地址轉換、字符串排序、蛇形矩陣與字符串加密

字符串與算法題詳解:最長回文子串、IP 地址轉換、字符串排序、蛇形矩陣與字符串加密 前言 在編程題訓練中,字符串相關的題目非常常見。本文將結合幾個典型的例題,詳細解析它們的解題思路和實現方式,幫助初學者循序漸進地掌握常用技…

從協同設計到綠色制造:工業云渲染的價值閉環

在智能制造、建筑工程、能源電力、船舶海工等工業場景中,3D可視化已從傳統的桌面端逐步向Web端遷移,Web 3D憑借其跨平臺、輕量化、實時交互等特性,已成為企業構建數字孿生、實現遠程協作、推動云端交付的重要工具。這場技術變革不僅改變了工業…

算法第五十一天:圖論part02(第十一章)

1.島嶼數量 99. 島嶼數量 🌟 思路總結 — DFS 版 1?? 問題本質 給定一個二維矩陣 grid,1 表示陸地,0 表示水 統計島嶼數量,每個島嶼由上下左右相鄰的陸地組成 本質是 在二維網格中找連通塊 的問題。 2?? 核心思路 遍歷矩陣…

杰里708n tws api 簡介

/** 通過搜索碼搜索tws設備*/int tws_api_search_sibling_by_code();/**打開可發現, 可連接,可被手機和tws搜索到*/int tws_api_wait_pair_by_code(u16 code, const char *name, int timeout_ms);int tws_api_wait_pair_by_ble(u16 code, const char *name, int tim…

高調光比 LED 恒流驅動芯片方案詳解AP5165B:36V/1A

AP5165B 是深圳市世微半導體有限公司推出的一款高性能、連續電流模式的降壓型(Buck)LED 恒流驅動芯片。該芯片適用于輸入電壓高于 LED 電壓的應用場景,可驅動單顆或多顆串聯的 LED,輸出電流最高可達 1A,廣泛用于非隔離…

【從零構建企業級線程池管理系統:Python并發編程實戰指南】

從零構建企業級線程池管理系統:Python并發編程實戰指南 技術博客 | 深入探索Python并發編程、Web開發與現代軟件架構設計的完整實踐 🚀 項目背景 在當今高并發的互聯網時代,線程池作為并發編程的核心組件,其管理和監控能力直接影…

飛牛系統總是死機,安裝個工具查看一下日志

崩潰轉儲 (kernel crash dump)如果你懷疑是內核 panic,可以開啟 kdump 或 kernel crash dump。 安裝:sudo apt install kdump-tools # Debian/Ubuntu sudo systemctl enable kdump 下次死機時,系統會把內存 dump 到 /var/crash 里。sudo syst…

2025年AI Agent技術深度解析:原理、應用與未來趨勢

一、引言隨著人工智能技術的飛速發展,AI Agent(智能體)作為人工智能領域的重要分支,正逐漸成為推動各行業智能化轉型的關鍵力量。AI Agent具備自主感知、決策和執行能力,能夠在復雜環境中完成特定任務,為人…

linux內核 - 內存分配機制介紹

在linux內核中,下面這張圖說明了系統中存在一個可以滿足各種內存請求的分配機制。根據你需要內存的用途,你可以選擇最接近你目標的分配方式。最底層、最基礎的分配器是 頁分配器(page allocator),它以頁為單位分配內存…

PyTorch生成式人工智能——ACGAN詳解與實現

PyTorch生成式人工智能——ACGAN詳解與實現0. 前言1. ACGAN 簡介1.1 ACGAN 技術原理1.2 ACGAN 核心思想1.3 損失函數2. 模型訓練流程3. 使用 PyTorch 構建 ACGAN3.1 數據處理3.2 模型構建3.3 模型訓練3.4 模型測試相關鏈接0. 前言 在生成對抗網絡 (Generative Adversarial Net…

Python + 淘寶 API 開發:自動化采集商品數據的完整流程?

在電商數據分析、競品監控和市場調研等場景中,高效采集淘寶商品數據是關鍵環節。本文將詳細介紹如何利用 Python 結合 API,構建一套自動化的商品數據采集系統,涵蓋從 API 申請到數據存儲的完整流程,并提供可直接運行的代碼實現。?…

2025.8.21總結

工作一年多了,在這期間,確實也有不少壓力,但每當工作有壓力的時候,最后面都會解決。好像每次遇到解決不了的事情,都有同事給我兜底。這種壓力,確實會加速一個人的成長。這種狼性文化,這種環境&a…

VS2022 - C#程序簡單打包操作

文章目錄VS2022 - C#程序簡單打包操作概述筆記實驗過程新建工程讓依賴的運行時程序安裝包在安裝時運行(如果發現運行時不能每次都安裝程序,就不要做這步)關于”運行時安裝程序無法每次都安裝成功“的應對知識點嘗試打包舊工程bug修復從需求屬性中,可以原…

在JAVA中如何給Main方法傳參?

一、在IDEA中進行傳參:先創建一個類:MainTestimport java.util.Arrays;public class MainTest {public static void main(String[] args) {System.out.println(args.length);System.out.println(Arrays.toString(args));} }1.IDEA ---> 在運行的按鈕上…

ORACLE中如何批量重置序列

背景:數據庫所有序列都重置為1了,所以要將所有的序列都更新為對應的表主鍵(這里是id)的最大值1。我這里序列的規則是SEQ_表名。BEGINENHANCED_SYNC_SEQUENCES(WJ_CPP); -- 替換為你的模式名 END; / CREATE OR REPLACE PROCEDURE E…

公號文章排版教程:圖文雙排、添加圖片超鏈接、往期推薦、推文采集(2025-08-21)

文章目錄 排版的基本原則 I 圖片超鏈接 方式1: 利用公號原生編輯器 方式2:在CSDN平臺使用markdown編輯器, 利用標簽實現圖片鏈接。 II 排版小技巧 自定義頁面模版教程 使用壹伴進行文章素材的采集 美編助手的往期推薦還不錯 利用365編輯器創建圖文雙排效果 排版的基本原則 親…

計算兩幅圖像在特定交點位置的置信度評分。置信度評分反映了該位置特征匹配的可靠性,通常用于圖像處理任務(如特征匹配、立體視覺等)

這段代碼定義了一個名為compute_confidence的函數,用于計算兩幅圖像在特定交點位置的置信度評分。置信度評分反映了該位置特征匹配的可靠性,通常用于圖像處理任務(如特征匹配、立體視覺等)。以下是逐部分解析: 3. 結果…

計算機視覺第一課opencv(三)保姆級教學

簡介 計算機視覺第一課opencv(一)保姆級教學 計算機視覺第一課opencv(二)保姆級教學 今天繼續學習opencv。 一、 圖像形態學 什么是形態學:圖像形態學是一種處理圖像形狀特征的圖像處理技術,主要用于描…

24.早期目標檢測

早期目標檢測 第一步,計算機圖形學做初步大量候選框,把物體圈出來 第二步,依次將所有的候選框圖片,輸入到分類模型進行判斷 選擇性搜索 選擇搜索算法(Selective Search),是一種熟知的計算機圖像…