SpringBoot入門-(2) Spring IOC機制【附實例代碼】

SpringBoot入門-(2) Spring IOC機制

Spring

Spring是一個當前主流的輕量級的框架,發展到形狀已經不僅僅是一個框架,而是形成以Spring為基礎的生態圈,如(Spring Boot,Spring Cloud,Spring Security等)

Spring 兩大核心技術

  • 控制反轉(IoC)
  • 面向切面編程(AOP)

本文先介紹其一

控制反轉(IoC/DI)

依賴注入(DI:Dependency Injection ):Spring通過創建容器的方式,來負責對象的創建、對象和對象之間關系的維護等

動機

在面向對象的系統設計中,底層的業務邏輯是由多個對象組成,對象之間通常存在復雜的聯系,導致系統的耦合度很高,例如:

public class UserServiceImp implements UserService{private UserDao userdao = new UserDaoImp();...}

上述UserServiceImp類實現UserService接口,其中創建的私有成員變量是通過UserDaoImp類創建出來的實例。

UserDaoImp的業務邏輯產生變化或出現錯誤,都有可能需要修改UserServiceImp的代碼,所謂產生了"牽一發而動全身"的系統高耦合度。

不難發現,系統越龐大,對象關系越復雜,系統耦合度越高,導致系統維護愈發困難。

因此,Spring橫空出世,解決對象之間耦合度過高的問題。后來從產品發展為生態圈。

概念

究竟什么是控制反轉?

先看下圖:

在這里插入圖片描述
首先是左圖的情況,假設其他一個齒輪需要修改或不轉動,都會導致其他的齒輪停止工作,這稱為高耦合度。而右圖,齒輪之間不存在依賴關系,工作相對獨立,不會影響到其他齒輪的正常工作。這表現的就是"控制反轉"的基本思想:

借助于“第三方”實現具有依賴關系的對象之間的解耦

齒輪之間的傳動全部依靠“第三方”了, 全部對象的控制權全部上繳給“第三方”IOC容器,主動創建變為了被動注入, 這就是“控制反轉”(依賴注入)這個名稱的由來

代碼

首先創建Maven項目(傳送門:SpringBoot入門-(1) Maven【概念+流程】-CSDN博客),pom.xml文件導入相關spring依賴,包括測試依賴:

    <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>RELEASE</version><scope>test</scope></dependency></dependencies>

注意,這里沒有定義依賴的版本,是通過父項目統一管理版本號

without Spring

我們先用常規的MVC架構實現一些簡單邏輯,后面對比Spring架構就可以明顯發現其優勢和作用。

首先我們實現一個非常簡易的商品存入數據庫的邏輯:

在這里插入圖片描述
部分代碼如下:

  • ProductDaoImpl

    package com.example.Dao;import com.example.Dao.ProductDao;
    import com.example.entity.Product;public class ProductDaoImpl implements ProductDao {//這里是模擬商品存入,并沒有真正存入數據庫@Overridepublic void saveProduct(Product product) {System.out.println("保存商品信息");System.out.println(product.toString());}
    }
    
  • ProductServiceImpl

    package com.example.Service;
    import com.example.entity.Product;
    import com.example.Dao.*;public class ProductServiceImpl implements ProductService{private ProductDao productDao =  new ProductDaoImpl();//其他業務邏輯,如檢查是否合法等@Overridepublic void saveProduct(Product product) {productDao.saveProduct(product);}
    }
    

可以看到在ProductServiceImpl中,我們通過new的方式創建實例對象并賦值給成員變量

測試代碼:

test目錄底下進行測試:

package com.example.Service;import com.example.entity.Product;
import org.junit.jupiter.api.Test;public class ProductServiceTest { //如果 Calculator 類和測試類處于相同的包或者符合 Java 的包訪問規則,那么測試類就可以直接訪問 ProductServiceImpl 類。@Testpublic void testSaveProduct() {ProductService productService = new ProductServiceImpl();productService.saveProduct(new Product(0, "test",12.7));}
}

可以看到控制臺輸出信息:
在這里插入圖片描述

with spring

我們現在使用spring框架實現相同的功能

  • 方式一:配置文件

首先新建spring的配置文件,如圖:
在這里插入圖片描述

命名為applicationContext,可以看到文件中已經存在默認的內容(默認生成的XML文件的NameSpace,<bean>就是關鍵的標簽。

容器中創建對象,本質就是在文件中配置一個bean

<beans></beans>中間添加我們想要創建的對象及注入依賴

    <bean id="productDao" class="com.example.Dao.ProductDaoImpl"/><bean id="productService" class="com.example.Service.ProductServiceImpl"><property name="productDao" ref="productDao"/></bean>

容器通過com.example.Dao.ProductDaoImpl類創建id為productDao的對象

對象屬性的賦值通過<property>標簽,需要在com.example.Service.ProductServiceImpl提供對應的setter方法:

    public void setProductDao(ProductDaoImpl productDao) {this.productDao = productDao;}

下一步,在測試程序中創建容器,并獲取指定對象進行測試。

public class ProductServiceTest {//如果 Calculator 類和測試類處于相同的包或者符合 Java 的包訪問規則,那么測試類就可以直接訪問 ProductServiceImpl 類。@Testpublic void testSaveProduct() {ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");ProductService productService = (ProductService) ac.getBean("productService");productService.saveProduct(new Product(0, "test",12.7));}
}

上述代碼中,我們先創建了容器,然后根據xml文件中的配置獲取對象,返回的類型是Object,注意轉換類型。

觀察到上述兩種方式,spring將層與層之間的聯系解耦,可以比較一下下面兩段代碼:

//解耦前
private ProductDao productDao =  new ProductDaoImpl();//spring
private ProductDao productDao;
//在配置文件中注入依賴
<bean id="productService" class="com.example.Service.ProductServiceImpl"><property name="productDao" ref="productDao"/>
</bean>

這樣,我們在"更換齒輪"的時候就不用去修改Service層的代碼,修改配置文件即可。(注意,配置文件依賴注入一定要在相應的地方添加setter方法,底層會進行調用)

  • 方式二: 注解實現IOC
  1. 注解+配置

當我們的項目很大的時候,使用配置文件就會出現問題,配置文件信息內容過大讓人眼花繚亂,所以spring提供了注解的方式。

在這里插入圖片描述
根據注解,我們可以把配置文件中的:

<bean id="productDao" class="com.example.Dao.ProductDaoImpl"/>

等效為:

@Repository("productDao")
//如果不給注解起名字,默認的名字為類名(首字母小寫)
public class ProductDaoImpl implements ProductDao {//這里是模擬示范@Overridepublic void saveProduct(Product product) {System.out.println("保存商品信息");System.out.println(product.toString());}
}

Spring 默認不使用注解裝配 Bean,因此我們需要在 Spring 的 XML 配置中,通過**context:component-scan** 元素開啟 Spring Beans的自動掃描功能

<context:component-scan base-package="com.example.*"></context:component-scan>

其中base-package是你希望自動掃描的路徑。

Bean的自動裝配

使用@AutoWired注解實現自動裝配,如:

public class ProductServiceImpl implements ProductService{@Autowiredprivate ProductDao productDao;
  1. 全注解

不使用spring配置文件,而是進行全注解開發,因此我們需要使用注解寫一個配置類實現和annotation.xml的功能。

在config/目錄下創建類文件:

@Configuration
@ComponentScan("com.example")
public class SpringConfig {
}

對應的測試代碼:

    @Testpublic void testSaveProduct() {ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);ProductService productService = ac.getBean("productService", ProductService.class);

當然也可以在配置類中使用@Bean標簽

@Configuration
@ComponentScan("com.example")
public class SpringConfig {@Bean(name = "productService")public ProductServiceImpl creat(){return new ProductServiceImpl();}
}

對應的測試代碼修改一句即可:

ProductService productService = ac.getBean(ProductService.class);

?

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

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

相關文章

備賽藍橋杯之第十六屆模擬賽3期職業院校組

提示&#xff1a;本篇文章僅僅是作者自己目前在備賽藍橋杯中&#xff0c;自己學習與刷題的學習筆記&#xff0c;寫的不好&#xff0c;歡迎大家批評與建議 由于個別題目代碼量與題目量偏大&#xff0c;請大家自己去藍橋杯官網【連接高校和企業 - 藍橋云課】去尋找原題&#xff0…

【AI大模型】提示詞(Prompt)工程完全指南:從理論到產業級實踐

【AI大模型】提示詞&#xff08;Prompt&#xff09;工程完全指南&#xff1a;從理論到產業級實踐 一、Prompt 提示詞介紹&#xff1a;AI的“密碼本” 1. Prompt的底層定義與價值 本質&#xff1a;Prompt是人與AI模型的“協議語言”&#xff0c;通過文本指令激活模型的特定推理…

Excel 小黑第12套

對應大貓13 涉及金額修改 -數字組 -修改會計專用 VLOOKUP函數使用&#xff08;查找目標&#xff0c;查找范圍&#xff08;F4 絕對引用&#xff09;&#xff0c;返回值的所在列數&#xff0c;精確查找或模糊查找&#xff09;雙擊填充柄就會顯示所有值 這個逗號要中文的不能英…

基于Spring Boot的冷鏈物流系統的設計與實現的設計與實現(LW+源碼+講解)

專注于大學生項目實戰開發,講解,畢業答疑輔導&#xff0c;歡迎高校老師/同行前輩交流合作?。 技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;…

python環境集成整理

接口測試過程中&#xff0c;可能會切換測試環境&#xff0c;通過配置相關信息修改 設計思路&#xff1a; 1、 準備各個環境配置文件信息&#xff0c;包括http、common 、redis、db 2、創建不同環境配置信息 測試環境&#xff1a;env_test.yml、 預生產環境:env_prepro.yml、生產…

動平衡仿真程序設計

以下是針對動平衡振動信號分析的模塊擴展方案&#xff0c;基于原有信號發生器架構進行增強&#xff1a; 一、動平衡專用信號生成器 // UnbalanceVibrationGenerator.h #pragma once #include "SignalGenerator.h" #include <vector>class UnbalanceVibration…

牛客周賽85 題解 Java ABCDEFG

A小紫的均勢博弈 判斷輸入的 n 是奇數還是偶數 import java.io.*; import java.math.*; import java.util.*;public class Main {static IoScanner sc new IoScanner();static final int mod(int) (1e97);static void solve() throws IOException {int nsc.nextInt();if(n%2…

python——UI自動化(1) selenium之介紹和環境配置

一、selenium介紹 selenium是一個第三方庫&#xff0c;python有很多庫&#xff1b; 1、什么是ui自動化? 通過模擬手工操作用戶ui頁面的方式&#xff0c;用代碼去實現自動化操作和驗證的行為。 2、ui自動化的優點&#xff1f; &#xff08;1&#xff09;解決重復性的功能測…

Can通信流程

下面給出一個更詳細的 CAN 發送報文的程序流程說明&#xff0c;結合 HAL 庫的使用及代碼示例&#xff0c;幫助你了解每一步的具體操作和內部原理。 一、系統與外設初始化 1.1 HAL 庫初始化 在 main() 函數開頭&#xff0c;首先調用 HAL 庫初始化函數&#xff1a; HAL_Init()…

15 數據結構及算法應用

15 數據結構及算法應用 15.1 算法策略區分 15.1.1、分治法 特征:把一個問題拆分成多個小規模的相同子問題&#xff0c;一般可用遞歸解決。 經典問題:斐波那契數列、歸并排序、快速排序、矩陣乘法、二分搜索、大整數乘法、漢諾塔。 15.1.2、貪心法 (一般用于求滿意解) …

基于大模型的唇裂手術全流程預測與應用研究報告

目錄 一、引言 1.1 研究背景與意義 1.2 研究目標與內容 二、唇裂相關醫學知識概述 2.1 唇裂的定義、分類與發病原因 2.2 唇裂對患者生理與心理的影響 2.3 傳統唇裂治療方法與局限性 三、大模型技術原理與應用基礎 3.1 大模型概述 3.2 適用于唇裂預測的大模型類型及特…

環境變量設置異常導致UOS文件管理器無法正常運行

編譯QT5.15.2&#xff0c;與UOS20.9的QT依賴沖突 現象原因解決方法 現象 重啟系統后UOS桌面變成黑色&#xff0c;沒有任何圖標&#xff0c;任務欄的應用本來是有預覽的&#xff0c;但也變得不可用。 原因 找了很久&#xff0c;查到原來是dde-file-manager未能正常啟動。直接…

《認知覺醒》改變的核心方法論

《認知覺醒》改變的核心方法論 一、認知覺醒的核心目標 改變 → 提升能力 → 獲得更好生活 二、大腦運作機制 腦區運算速度作用特點本能腦1.1億次/秒自動化反應&#xff0c;能量消耗低情緒腦1.1億次/秒情感驅動型決策?理智腦?40次/秒戰略指揮官角色 關鍵差異&#xff1a…

Python中的字典:深度解析與應用實踐

一、字典的本質與特性 Python字典&#xff08;Dictionary&#xff09;是以**鍵值對&#xff08;Key-Value Pair&#xff09;**形式存儲數據的無序集合&#xff0c;使用大括號{}定義。其核心特性包括&#xff1a; 快速查找&#xff1a;基于哈希表實現&#xff0c;通過鍵&#…

【藍橋杯python研究生組備賽】005 數學與簡單DP

題目1 01背包 有 N 件物品和一個容量是 V 的背包。每件物品只能使用一次。 第 i 件物品的體積是 vi&#xff0c;價值是 wi。 求解將哪些物品裝入背包&#xff0c;可使這些物品的總體積不超過背包容量&#xff0c;且總價值最大。 輸出最大價值。 輸入格式 第一行兩個整數&a…

2024年國賽高教杯數學建模E題交通流量管控解題全過程文檔及程序

2024年國賽高教杯數學建模 E題 交通流量管控解題 原題再現 隨著城市化進程的加快、機動車的快速普及&#xff0c;以及人們活動范圍的不斷擴大&#xff0c;城市道路交通擁堵問題日漸嚴重&#xff0c;即使在一些非中心城市&#xff0c;道路交通擁堵問題也成為影響地方經濟發展和…

穿越是時空之門(java)

emm&#xff0c;之前做過一道類似的題目&#xff0c;但是這次又忘了 一開始的錯誤代碼 package Lanqiao;import javax.swing.plaf.synth.SynthTextAreaUI; import java.math.BigInteger;/*** author zb* date2025/3/19 21:33*/ public class L19701 {public static void main…

npm : 無法加載文件 C:\Program Files\nodejs\npm.ps1,因為在此系統上禁止運行腳本的處理方法

1、安裝了node.js后&#xff0c;windows powershell中直接輸入npm&#xff0c;然后就報錯 2、出現原因&#xff1a;權限不夠 系統禁用了腳本的執行&#xff0c;所以我們在windows powershell輸入npm -v的時候&#xff0c;就會報上面的錯誤。 3、解決 Set-ExecutionPolicy Un…

藍橋杯單片機之AT24C02(基于自己對AT24C02的學習和理解)

一、先用抽象法說明原理&#xff0c;讓原理變得簡單易懂&#xff1a; 1、向AT24C02寫入數據&#xff1a; 有個關系戶&#xff0c;他想安排自己的兒子進某個大廈里某個樓層的公司&#xff0c;那么他就要先找到這個公司的地址&#xff0c;然后再找到該公司是第幾樓&#xff0c;最…

Java面試易忽略知識點

1. CompletableFuture中thenApply()與thenCompose()的區別 考察點&#xff1a;組合式異步編程 解析&#xff1a; ?**thenApply()**&#xff1a;接收前序任務結果&#xff0c;返回普通對象&#xff08;同步轉換&#xff09;&#xff0c;適用簡單數據處理。?**thenCompose()*…