后端之路第二站(正片)——SprintBoot之:分層解耦

很抽象,我自己也不好理解,僅作為一個前端轉后端的個人理解

一、先解釋一個案例,以這個案例來分析“三層架構”

這里我先解釋一下黑馬程序員里的這個案例,兄弟們看視頻的可以跳過這節課:Day05-08. 請求響應-響應-案例_嗶哩嗶哩_bilibili?看我這里的解說就可以,因為他這里把前端的文件塞到后端這里弄,還要解析XML文件來獲取數據,完全沒必要,沒有任何地方會這樣做了,直接看我的解釋過一遍就行

首先他把一個寫了我們要的數據的XML引入到spring boot項目中,我們可以理解類似為前端有時會在一個js文件里寫一堆數據用于測試、模擬后端數據的(但實際后端應該是連接數據庫,數據是來源于數據庫的

然后他的這個鬼XML文件里的數據里還不直接寫明白“性別”是(男/女),而是寫成(1/0),“職業”也是,非要寫成(1/2/3),然后還得到獲取數據的地方把(1/0)、(1/2/3)解析成(男/女)、(講師/班主任/....),這不是脫褲子放屁,多此一舉嗎

于是,他又去請求頁面,再解析獲取到XML數據后,再去進行以上這些邏輯處理......我們暫且理解為vue里的<script></script>這部分的邏輯處理吧

最后再把這些數據發送請求

(我只是為了方便各位理解!!不是一個東西啊!!)

那么結合前端我們可以理解為有點類似“表單數據傳送”,我們先獲取表單的所有數據,然后進行邏輯處理:拆分出數據然后封裝進一個對象,最后發送請求給后端

但是看看這一坨代碼這么亂......

二、三層架構是啥

那么分析一下一坨代碼,可以看出其實可以分成三大塊:

【數據訪問】:解析數據源,拿到數據

【邏輯處理】:把數據抽出來進行一些邏輯處理

【接收請求、響應數據】:把數據封裝好給回前端

那么我們應該把這三塊分開來寫,這樣的話,那一部分出問題可以直接找到這一部分查看問題

因此人們就規定應該分成這三塊:

這三塊要做的事:

  • Controller:控制層。接收前端發送的請求,對請求進行處理,并響應數據。

  • Service:業務邏輯層。處理具體的業務邏輯。

  • Dao:數據訪問層(Data Access Object),也稱為持久層。負責數據訪問操作,包括數據的增、刪、改、查。

那么這個三層架構的執行流程是:

1、前端發起的請求,由Controller層接收(Controller響應數據給前端)

2、Controller層調用Service層來進行邏輯處理(Service層處理完后,把處理結果返回給Controller層)

3、Serivce層調用Dao層(邏輯處理過程中需要用到的一些數據要從Dao層獲取)

4、Dao層操作文件中的數據(Dao拿到的數據會返回給Service層)

好,那么與之相反的,我們開發人員寫代碼的流程是:(切記!不要去管這里代碼寫了什么,過一遍流程就行!!!這里的代碼不值得去花時間學習)

1、在【請求處理類】同級目錄下創建一個【dao】目錄

2、然后在【dao】目錄下創建一個代表該獲取的數據的接口(java里的接口,不是請求數據的那個接口)

然后創建這個接口的實現類(連同包含實現類的文件夾目錄一塊),implements實現這個類,然后把獲取數據、解析數據的內容放到這里實現

記得把數據return出去

3、然后同樣的流程【創建service目錄】——>【創建代表數據的接口】——>【然后創建(連文件夾包一起)實現這個接口的實現類】——>【記得先創建并調用Dao的實現類對象,因為現在數據在Dao那】——>【然后service的實現類的內容就是處理數據的邏輯】

4、最后,創建【controller】目錄,把一個【請求處理類】放到【controller目錄】——>【然后現在完整、處理好的數據源在service實現類】——>【在方法外面創建service的實現類對象】——>【然后方法里調用service實現類對象,拿到數據】——>【然后通過請求return出去,響應給前端】

總結就是:

開發視角:數據源從外部到Dao——>然后我們要用service獲取Dao的數據,然后處理——>然后Controller最后獲取service處理好的數據,響應回前端

前端視角:發送請求給到Controller——>Controller找service要——>service找Dao要

三、分層解耦

1、理解耦合是什么?

耦合問題

首先需要了解軟件開發涉及到的兩個概念:內聚和耦合。

  • 內聚:通俗講就是各功能功能模塊跟自身功能聯系

比如【Controller】的功能是接受請求、實現請求接口、響應回前端,【service】的功能是處理數據、做邏輯處理,【Dao】功能就是解析數據

那么這三塊分開,各自里面的內容是各自的功能實現,這就是【內聚高】,互不影響

那么如果不分開,這三個內容的代碼全堆【Controller】那里,那么【Controller】本來功能只用實現請求、響應前端的,現在當黑奴,一人干幾份活,這就是【內聚低

  • 耦合:衡量軟件中各個層/模塊之間的依賴、關聯的程度。

比如【Controller】接收到前端請求后,找數據需要通過調用【service】來獲取數據,而【service】找數據也得靠調用【Dao】來獲取數據,這種聯系就叫【耦合

當他們是三個部門,當少了一方部門、或者其中一個部門要改名字啥的,會牽連到三個部門,這就是【耦合高

但是軟件工程開發要求【內聚低耦合高

那么就要分層解耦

2、分層解耦是什么?

那么現在我們要解耦,該怎么辦?

我們思考一下【Controller】調用的是什么?是【service的實現類】。

那么【Controller】調用的時候其實不管你是叫【service_A】還是【service_B】,只要是implement實現了【service】這個接口的實現類,【Controller】都需要

那么就可以有這么一個外部【容器】,他裝有實現了【service】接口的【實現類】,當【Controller】需要的時候就去【容器】找有沒有,有的話就拿去用

(我們理解為“華為公司”需要招聘員工,不管你是清華學子、還是北大學子,只要你是實現、集合了“985/211重本院校”的學生,他都要。那么我們就可以設一個“人才市場”,里面有各個[實現、集合了“985/211重本院校”的學生],華為公司需要誰,就去人才市場要)

這里還有幾個概念要知道:

控制反轉: Inversion Of Control,簡稱IOC。對象的創建控制權由程序自身轉移到外部(容器),這種思想稱為控制反轉。(通俗理解給自己簽訂賣身契,賣到人口市場,隨時被人交易)

依賴注入: Dependency Injection,簡稱DI。容器為應用程序提供運行時,所依賴的資源,稱之為依賴注入。(通俗理解為買家跟人口市場綁定了,有符合要求的就自動買了)

IOC容器中創建、管理的對象,稱之為:bean對象 (理解為人口市場的奴隸hh)

四、IOC控制反轉 + DI注入依賴

1、首先先把【Controller】【service】【Dao】之間的聯系刪掉

(理解為華為公司取消了跟某些高校的強制合作,不要固定那幾個高校推薦內推的學生,選擇讓人才市場給自己分配員工)

2、然后開始【控制反轉】

給【service】和【Dao】加上容器注解【@Component】

加上它,就意味著要將當前類“交給”IOC容器管理,成為IOC容器里的一個bean對象

(可以理解為高材生把自己的簡歷投放到人才市場了,由人才市場保管自己的簡歷)

3、然后開始【依賴注入】

要將【Controller】綁定上【依賴注入】,加上注解【@Autowired】

加上【@Autowired】就意味著運行時,IOC容器會提供該類型的bean對象,并賦值給該變量

(理解為華為公司把自己的HR丟人才市場,任由HR發揮,只要符合要求就直接招進公司)

4、那如果要更換bean對象怎么辦?

加入我有一個【service】實現類【A】,我現在不要用它了,我要改成【B】怎么辦?

把【A】的【@Component】注釋掉,在【B】上面加上【@Component】就行了......就這么簡單

五、Bean另外的衍生注解

注解說明位置
@Component聲明bean的基礎注解不屬于以下三類時,用此注解
@Controller?@Component?的衍生注解標注在控制器類上
@Service@Component的衍生注解標注在業務類上
@Repository@Component的衍生注解

標注在數據訪問類上

(由于與mybatis整合,用的少)

是啥個意思呢?

意思是【控制反轉】有的時候不一定要用【@Component】,其實【Controller】、【Service】、【Dao】的【控制反轉】可以分別用【@Controller】、【@Service】、【@Repository】來注解

然后因為其實【@Service】、【@Repository】的源代碼里其實是包含了【@Component】的,所以用【@Service】、【@Repository】就等于用【@Component

但是spring boot的web開發里,【Controller】控制器不能用【Component】,不過它除了注解【@Controller】,我們之前講過【@RestController】也包含了【@Controller】,所以用【@ReastController】就可以了

六、主包(主目錄)外面的包的Bean對象掃描不到

問題:使用前面學習的四個注解聲明的bean,一定會生效嗎?

答案:不一定。(原因:bean想要生效,還需要被組件掃描,比如你主包外面的bean對象就不會生效)

那就要用到組件掃描:【@ComponentScan】

但是【@ComponentScan】并不是亂用的,首先回到我們的【啟動類】

我們知道【@SpringBootApplication】是【啟動類】注解,但其實他還是包含了【@ComponentScan】的組件掃描注解,它可以掃描【當前包以及其自包里的所有的Bean】

但是要是Bean在主包的外面怎么辦?

那這是才只能手動寫【@ComponentScan】來導入要掃描的“包(目錄)”,并且還得帶上原本當前這個“包(目錄)”,因為會覆蓋下面的【@SpringBootApplication】

具體語法是:

@ComponentScan( { "外部含Bean的那個包" , "當前包" } )

但其實不建議這樣,一般情況推薦全部Bean都放到啟動類的包下,方便全局掃描

七、DI注入依賴選擇一個Bean來注入

我們前面說過,如果想要注入依賴的時候,容器里有兩個符合條件的實現類,只選擇其中一個的話,就把另一個實現類的【@Component】注釋掉

但是如果我容器里有成千上萬個符合條件的【實現類Bean】怎么辦?難道我要全部一個一個去注釋嗎?

比如下面這個例子,我有兩個都寫了【@Sevice】(怕忘了,再提醒一下這個也等于@Component)的【service實現類Bean】

然后此時再運行時就會報錯,因為超過兩個同類型的實現類Bean

這是因為注入依賴里的注解【@Autowired】,它是根據類型來自動獲取容器里所有的符合的實現類Bean的,那么容器里有兩個就拿兩個,有十個就拿十個,而一旦超過了一個Bean就會報錯

那么解決辦法有三個

1、(不太推薦)@Primary:在要希望生效的那個Bean上添加這個注解

2、(可以)@Qualifier:在要注入依賴的地方、@Autowired前面指定你要哪一個Bean

3、(非常推薦)@Resouce:直接在注入依賴的地方,去掉@Autowired,替換成這個并指定要哪個Bean

1、@Primary是在要希望生效的那個Bean上添加這個注解,不推薦是因為跟注釋【@Component】其實是半斤八兩的啊.......你還得去一個一個找到這個Bean,然后再Bean的代碼里改

2、@Qualifier就是在要注入依賴的地方、@Autowired前面指定你要哪一個Bean,這樣確實很方便,直接指明要誰,美中不足就是,我感覺跟@Autowired有點重復,兩在一塊總感覺有點多余

另外解釋為什么【實現類EmpServiceA】在@Qualifier這要寫成【empServiceA】,因為我前面懶,省略了講:Bean對象的名字其實是【實現類】名字的首字母小寫......而不是它原本的實現類的那個名字

3、@Resouce為甚推薦?因為它是直接在注入依賴的地方,去掉@Autowired,替換成@Resouce,并寫上指定要哪個Bean的名字就行

為什么它可以直接不要【@Autowired】,因為【@Resouce】是根據名字來注入Bean的!!

另外【@Primary】跟【@Qualifier】是spring boot框架提供的,而【@Resouce】是Java的JDK提供的

ok,本爺的spring?boot學習先告一段落,后面先學MySQL,然后等再學回spring boot的時候再更新博客

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

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

相關文章

【webrtc】m98:Call的創建及Call對音頻接收處理

call中多個流共享相同的輔助組件 這幾個是與外部共用的 線程傳輸send控制module 線程任務隊列工廠call的輔助組件中各種統計以及接收測的cc是自己創建的 call自己的多個輔助組件是外部傳遞來的 call 創建多個接收流 這里用一個set 來保存所有指針,并沒有要map的意思:

【因果推斷從入門到精通二】隨機實驗3

目錄 檢驗無因果效應假說 硬幣投擲的特殊性何在&#xff1f; 檢驗無因果效應假說 無因果效應假說認為&#xff0c;有些人存活&#xff0c;有些人死亡&#xff0c;但接受mAb114治療而不是ZMapp與此無關。在174例接受mAb14治療的患者中&#xff0c;113/17464.9%存活了28天&…

【MySQL精通之路】InnoDB(6)-磁盤結構

主要博客&#xff1a; 【MySQL精通之路】InnoDB存儲引擎-CSDN博客 1 表 2 索引 【MySQL精通之路】InnoDB(6)-磁盤結構(2)-索引-CSDN博客 3 表空間 【MySQL精通之路】InnoDB(6)-磁盤結構(3)-表空間-CSDN博客 4 雙寫緩沖區 【MySQL精通之路】InnoDB(6)-磁盤結構(4)-雙寫緩沖…

修改MySQL root用戶密碼

ALTER USER ‘root’‘localhost’ IDENTIFIED BY ‘new_password’; ALTER USER ‘root’‘%’ IDENTIFIED BY ‘new_password’; 》 SET GLOBAL read_only OFF; select * from mysql.user;

Java入門基礎學習筆記47——ArrayList

什么是集合呢&#xff1f; 集合是一種容器&#xff0c;用來裝數據的&#xff0c;類似數組。 有數組&#xff0c;為什么還要學習集合呢&#xff1f; 數組定義完成并啟動后&#xff0c;長度就固定了。 而集合是大小可變&#xff0c;開發中用的最多的。 集合的特點&#xff1a;大…

匯聚榮科技有限公司優點有哪些?

在當今快速發展的科技時代&#xff0c;企業之間的競爭愈發激烈。作為一家專注于科技創新與研發的公司&#xff0c;匯聚榮科技有限公司憑借其卓越的技術實力和創新能力&#xff0c;在業界樹立了良好的口碑。那么&#xff0c;匯聚榮科技有限公司究竟有哪些優點呢?接下來&#xf…

C++利用TinyXML讀取XML文件

TinyXML是什么&#xff1f; TinyXML是一個輕量級的C XML解析器&#xff0c;它提供了一種簡單的方法來解析和操作XML文檔。TinyXML被設計為易于使用和集成到C項目中&#xff0c;并且非常適合處理小型XML文件。 以下是TinyXML的一些主要特點和優點&#xff1a; 輕量級: T…

OSPF問題

.ospf 選路 域內 --- 1類&#xff0c;2類LSA 域間 --- 3類LSA 域外 --- 5類&#xff0c;7類LSA --- 根據開銷值的計算規則不同&#xff0c;還分為類型1和類型2 ospf 防環機制 區域內防環&#xff1a;在同一OSPF區域內&#xff0c;所有路由器通過交換鏈路狀態通告&#xff…

VUE面試題(3)--vue常見面試題

1.vue優點 低耦合。視圖(View)可以獨立于Model變化和修改,一個ViewModel可以綁定到不同的"View"上,當View變化的時候Model可以不變,當Model變化的時候View也可以不變。 可重用性。你可以把一些視圖邏輯放在一個ViewModel里面,讓很多view重用這段視圖邏輯。 …

226.翻轉二叉樹

翻轉一棵二叉樹。 思路&#xff1a; 指針做交換 用遞歸&#xff08;前序or后序&#xff0c;中序不行&#xff09; 前序&#xff1a;中左右 遍歷到“中”的時候&#xff0c;交換它的左右孩子 然后分別對它的左孩子和右孩子使用“交換函數”&#xff08;定義的&#xff09;&a…

【網絡版本計算器的實現】

本章重點 理解應用層的作用, 初識HTTP協議理解傳輸層的作用, 深入理解TCP的各項特性和機制對整個TCP/IP協議有系統的理解對TCP/IP協議體系下的其他重要協議和技術有一定的了解學會使用一些分析網絡問題的工具和方法 ?注意!! 注意!! 注意!! 本課是網絡編程的理論基礎.是一個服務…

零基礎學Java第二十二天之迭代器 Iterator

迭代器 Iterator 的理解和相關集合 使用 1、理解 迭代器&#xff08;Iterator&#xff09;是設計模式中的一種&#xff0c;它允許程序員遍歷容器&#xff08;例如列表、集合等&#xff09;中的元素&#xff0c;而無需了解容器底層的實現細節。在編程中&#xff0c;迭代器提供了…

?第18章:JDK8-17新特性

1. 新特性概述 > 角度1&#xff1a;新的語法規則 &#xff08;多關注&#xff09;比如&#xff1a;lambda表達式、enum、annotation、自動拆箱裝箱、接口中的默認方法和靜態方法、switch表達式、record等> 角度2&#xff1a;增加、過時、刪除API比如&#xff1a;新的日期…

《子數整數》

描述 對于一個五位數a1?a2?a3?a4?a5?&#xff0c;可將其拆分為三個子數&#xff1a; sub1?a1?a2?a3? sub2?a2?a3?a4? sub3?a3?a4?a5? 例如&#xff0c;五位數20207可以拆分成 sub1?202 sub2?020(20) sub3?207 現在給定一個正整數K&#xff0c;要求你編程求…

【系統架構師】-論文-系統安全性與保密性設計

1、摘要: 2018 年初&#xff0c;我所在的公司為一票務公司開發開票業務平臺的建設。我在該項目中擔任系統架構設計師的職務&#xff0c;主要負責設計平臺系統架構和安全體系架構。該平臺以采用 B/S 架構服務用戶&#xff0c;采用”平臺應用”的模式解決現有應用單機獨立開票的模…

【YOLOv5/v7改進系列】替換激活函數為SiLU、ReLU、LeakyReLU、FReLU、PReLU、Hardswish、Mish、ELU等

一、導言 激活函數在目標檢測中的作用至關重要&#xff0c;它們主要服務于以下幾個關鍵目的&#xff1a; 引入非線性&#xff1a;神經網絡的基本構建塊&#xff08;如卷積層、全連接層等&#xff09;本質上是線性變換&#xff0c;而激活函數通過引入非線性&#xff0c;使得網絡…

urllib3 發起https請求時報錯 certificate verify failed

情況描述 近期需要訪問https的一個API接口同步數據&#xff0c;在辦公主機完成urllib3初步的測試以后&#xff0c;到測試環境驗證發現無法請求&#xff0c;報錯&#xff1a; 提示&#xff1a;解決辦法可以直接到第四節查看 一、提示 SSL 認證失敗 OpenSSL.SSL.Error: [(SSL …

保安維穩,四信以科技構筑高速公路安全智慧防線

近日&#xff0c;廣東梅大高速發生嚴重塌方事故&#xff0c;造成了嚴重的人員傷亡和財產損失。這一事件在公眾心中敲響了安全的警鐘&#xff0c;再次引起了公眾對于交通設施運營安全性的重點關注。 國務院安委會辦公室和國家防災減災救災委員會辦公室等主管機構先后印發緊急通知…

Spring Security整合Gitee第三方登錄

文章目錄 學習鏈接環境準備1. 搭建基本web應用引入依賴ThirdApp啟動類創建index頁面application.yml配置訪問測試 2. 引入security引入依賴ProjectConfig訪問測試 第三方認證簡介注冊gitee客戶端實現1引入依賴application.yml配置文件創建index.html頁面啟動類InfoControllerPr…

【數學建模】儲藥柜的設計

2014高教社杯全國大學生數學建模競賽D題目 題目描述 儲藥柜的結構類似于書櫥&#xff0c;通常由若干個橫向隔板和豎向隔板將儲藥柜分割成若干個儲藥槽(如圖1所示)。為保證藥品分揀的準確率&#xff0c;防止發藥錯誤&#xff0c;一個儲藥槽內只能擺放同一種藥品。藥品在儲藥槽…