[請益] Spring boot的依賴注入降低耦合的例子
推文有個連結有解答我的疑惑
感謝bron大
文章有點長
先說說我對依賴注入的理解
Spring boot
依賴注入大致有三種方式
透過建構子的 透過setter的 或是 field
這三種都可以透過@Autowired註解來達到依賴注入的效果
我自己想到的建構子的舉例是
假設有兩個類 Address 和 Employee好了
1.
public class Address {
String Country;
String City;
String Street;
public Address(String country, String city, String street) {
Country = country;
City = city;
Street = street;
}
}
2.
public class Employee {
String sex;
String name;
Address address;
// 沒有依賴注入的方式
public Employee(String Country,String City,String Street,String
sex, String name ) {
this.sex=sex;
this.address = new Address( Country, City,Street );
this.name=name;
}
// 有依賴注入的方式
public Employee(String sex, String name, Address address) {
this.sex = sex;
this.name = name;
this.address = address;
}
}
在上面的例子當中可以發現,如果哪一天
Address這個類新增了一個屬性叫 phoneNumber好了
沒有依賴注入的方式,必須要更改 Employee 的
this.address =new Address(Country,City,Street,phoneNumber)
而有依賴注入的方式確實降低了耦合
因為他不用更改Employee的建構方式
所以我理解依賴注入可以降低耦合
所以我理解依賴注入可以降低耦合
所以我理解依賴注入可以降低耦合
但我的問題是Spring boot 的 autowird annotation 有幫助我們降低耦合嗎
在常見的開發中 我們經常都會有 Dao 以及 Service
假設我有兩個 Dao 好了 分別是 Dao1 和 Dao2
以及一個Service
Dao1
public class Dao {
public void sayhi() {
System.out.println("hello");
}
}
Dao1
public class Dao {
public void sayhi() {
System.out.println("hello");
}
}
Dao2
public class Dao2 {
public void saygoodbye() {
System.out.println("say goodbye");
}
}
如果我不在service上面使用autowired
我的service會是
public class Service {
Dao1 dao=new Dao1();
Dao2 dao2=new Dao2();
public void sayhi() {
dao.sayhi();
}
public void saygoodbye() {
dao2.saygoodbye();
}
}
如果我使用了@Autowired註解
那我只是將
Dao1 dao=new Dao1();
Dao2 dao2=new Dao2();
替換成
@Autowired
Dao1 dao
@Autowired
Dao2 dao2
我想請問所以我使用了Autowired註解
我知道我可以不需要使用new 來建構實體
但 Spring 真的有幫我降低耦合嗎
即使我換成 setter 配合 autowired的方式好了
那個 setter也是要我自己去撰寫
Spring 幫我降低了耦合甚麼?
我的問題簡單來說就是
我知道依賴注入可以降低耦合
但Spring boot透過 @Autowired註解幫我降低耦合在哪
謝謝
p.s 因為面試的時候常常被面試官問說懂不懂甚麼是
控制反轉還有DI,我基本上舉例都舉 Address還有 Employee的例子
但當我反問下面例子的時候,他們好像也說要再回去想一下...
只有其中一個就說更複雜的例子會用到,但也沒說甚麼是更複雜的例子QQ
--
當有需要抽換實作的時候
在你理解前應該先完全不靠 spring 的功能,只靠 java
本身來做依賴注入,然後判斷有沒有真的有效就是你的類
可以把依賴的東西改用mock替換。那等你都弄好後開始不
斷的堆積業務邏輯時,就會發現初始化的地方會有一堆 n
ew constructor 然後再傳進另一個 new constructor,那
這時候一個像 spring 這樣的框架就可以用各種方式來幫
助你避免自己寫這些 new,就可以避免一些麻煩。 但我是
喜歡自己手動操作啦,靠框架的話整個生命周期很難看懂
。
我覺得任何DI framework都跟singleton 87%像邪惡
個人覺得方便測試時去 mock,平常用 Laravel 的經驗
Polymorphism
通常是autowired interface啦,再依參數配置決定要使用
簡單的例子就是更換DB driver
哪個實作上面那interface的component
@Autowired只是依類名或型別幫你在Spring容器生物件
DI與IoC才是低耦合的關鍵,與@Autowired無關
可是如果DI要我自己寫的話,Spring幫我做了啥,單純
的控制反轉有降低耦合嗎?
Spring幫你new物件並注入到使用的對象屬性中
還有上面Dao1 Dao2例子有誤,DI是從外面set進來
我的第一個例子應該是DI吧,把ADDRESS注入到Employee
當中
即使用Spring,不用自己寫new,可是建構子還是要自己寫
阿,降低了什麼功夫呢
幫你搞定層層的依賴關係
你可以試試不用Spring自己寫依賴注入,你就知道差異
我第一個例子就沒有依賴Spring 阿 地址跟員工那個
spring就是做掉你自己舉的例子,不然誰要往兩個class傳
dao進去?
你後面舉的自己new dao的行為,就等於你前面沒有做DI的
舉例了
我看下來只覺得原po寫太少了 哈哈哈哈
今天是dao你感覺比較單純無法,如果你要new的是service
呢?視你的專案複雜度,一個service可能會有10幾20個建
構子需要你自己new出來,而service互相依賴不會只有有
兩個這樣簡單的情況
我有試著在Controller當中去new service @RestController public class Controller { Service service=new Service( ); @GetMapping("test") public void saysomething() { service.saygoodbye(); service.sayhi(); } } 即使Service 裡面需要20個DAO好了 在Controller裡面new Service不也一樣只要 一行 Service service=new Service( ); 另外如果是setter 或是 Constructor方式的 DI 就我的理解 setter和建構子也是要自己寫 Spring 不會幫你產生 那我這樣看起來好像只是幫你從 new 換成了 @Autowired 這樣真的看不太出來 降低了甚麼耦合 因為建構子也是要自己寫啊 我覺得我好像陷入了泥淖中了QQ 翻了很多網頁,舉的例子大都跟我自己舉的 員工還有地址的差不多
※ 編輯: ntpuisbest (118.167.157.11 臺灣), 03/31/2022 22:36:56可以看看跟qualifier的搭配
要以類別與類別間的關係來看是否降低耦合吧?
降低耦合的定義應該不是叫大家可以少寫code哈哈
不用@Autowired就要寫上面連結中那坨new
20個dao只是一行嗎?那你試試new 20個都有20個dao的ser
vice
其實有在寫mockito的應該都體會過,當service耦合太嚴
重時,寫test有多痛苦,最後都會順便解耦XD
你寫工具給別人用比較會需要. 寫商業邏輯不太用的到
不確定 @Qualifier 能不能解答到你的疑惑?
運算的過程不想變動, 但又需要把產生的實例替換掉的情況下
就用到你的例子
謝謝bron大,我好像懂了,qualfied還在看@@
不懂正常,因為例子太爛,簡單的new感受不到這東西的
用處
你試試"new"個jdbc connection就知道了
會有spring好像沒幹事的錯覺,是因為作者是你自己,你
可以掌控那些複雜的service建構子,當多人協作時有人需
要使用你的service,還需要搞懂那些建構子的邏輯跟用法
,那就是一場災難,更別提那個人的service立刻又跟那些
建構子用途的物件耦合,每個人都這樣就沒完沒了
重點在 依賴於介面 而不依賴於實作
要能自己 new, 就綁死實作的 package/class 了
給 spring 生, 自己只綁介面定義 實作就可替換
降低耦合和少寫code是兩回事
整篇看完了 你要補的地方是 code to interface 的概念
先了解 interface 再來看 dependency injection 會較易懂
例如你有個 Dao interface 他有兩個實作 Dao1 和 Dao2
用 DI 可以在你的 Service 裡面去指定用哪一個實作
感謝上面所有大大 尤其是bron大,謝謝 ok 謝謝,我對介面的理解只有降低耦合 但跟di的關聯還沒補上 謝謝
※ 編輯: ntpuisbest (49.216.186.239 臺灣), 04/01/2022 00:35:55其實你舉的 service 例子不是解耦合喔 試想你若真的要在
service 中同時用到 Dao1 跟 Dao2 那怎會有解偶合的問題
當你會需要偶爾使用Dao1 偶爾使用 Dao2 甚至未來改成Dao3
才會需要解耦合 因為你把 Service 跟 Dao 解耦合了
更改 Dao 實作時 就不會動到 Service
你第一個例子,地址,通常不會視為DI吧,比較像ddd的v
alue object
我也有類似的問題,如果建構子會吃參數
如果要在spring上是不是最好改寫為另外set進去比較好
不然常常會寫一堆bean,好像沒有比較方便
但如果要用時再抓來set,物件的命名又會很混亂
一句話:DI並不解決耦合問題,DI只是幫助你更輕鬆的
測試並且轉換實作的時候不需要大量改動code
樓上正解
不管是依賴介面別依賴實作,還是用DI,都是解決掉你的
耦合問題,才有後續帶來的輕鬆測試跟切換實作,避免大
量改動code,他們都是解耦過程的一部分
會感覺不到DI好處,大概只能親身經歷過痛過強耦合的proje
ct才比較能體會
當你打算寫單元測試就會懂DI的好處了
@Autowired找到完全同一個concrete class的bean來注入本來
就沒有降低耦合,可以找到相容的實作(實作interface的bean
或subclass的bean)才有降低耦合
Autowired介面,搭配profile註解,可以在不同環境使用不
同實作
關於di,spring in action有個騎士出任務的範例,還蠻有
趣的
你可以A一下91哥的文 id是landlord
他有個土砲重構的範例滿不錯的
spring 只是稍微降低耦合。主要降低的是多用介面,多寫
幾層
不想講但還是講一下好了 它就只是偵測你包內的
annotation並且儲存起來(map) 需要的時候取用初始化
而已 依賴注入本身不是問題 問題是使用annotation的
依賴注入 專案大了以後 一堆初始化流程你都不見得能
夠掌握 更別說annotation設值所造成的影響
然後這樣的初始化效能肯定比你直接new來的差
介面的話更是扯 你直接改個類不就得了... 當然如果
習慣非常好 用annotation也都無所謂 但你不一定是一
一個人開發
用這些框架有時候就不是人在使用工具 是人被工具玩
更準確的是人寫工具的惡意 而非工具本身自主
無腦開發你才有人生 耗在這沒意義的事情才糟糕
樓上肯定沒用到request、session、refresh scope
才會覺得spring DI只是個map存起來這麼簡單
當然不是講的這麼大致方向 剩下的就只是應用再應用
講的這些真的要自己寫框架不難寫
只是個人不會遇到一個問題解決了再創造一個名詞
光看這些其實很容易眼花撩亂 還是學習真的知識比較好
Java 哈哈 Java
Old school try hard language
搞笑的語言就是只能搞笑
去除掉springBoot,IoC、DI和DIP這些概念又不是Java獨有
,說Java搞笑跟這篇文章的關聯真是無法理解!?
樓上找給我看除了 Java 以外還有哪個語言什麼事都要 anno
tations ,設定檔,框架魔法和 reflection 才能做的?真
的笑死
嗯嗯,您說得對
20
在這個時代依賴注入最重要的用途,特別是在後端開發是讓Application 在多個不同的 環境下(Development, Production, local, etc) 能夠根據profile 組出能正確執行的Application 多型在這裡當然有他的地位,但是一般來說,大部分不接觸system boundary的service objects 是不太需要多型的,如果是java,那種一個interface 只有一個implementation2
來補一下 "如何驗證效果" 的部份 首先假設情境, A 是你的 Web App B 是那個要被 Spring 注入的東西, 假設在 "外部" "其它人開發的 jar" 裡面 驗證的項目 1. B "改變" 時, A 需要做哪些事?10
很久沒寫Java了 就個人觀念提供簡單思考線索 基本上根據你的內容覺得你對解耦合還沒有很理解 講直白一點 當你import類別就是耦合了17
先講結論: DI(Dependency Injection) 跟 IoC(Inversion of Control) 的原始目的都不是解耦 接著說明一下 DI 跟 IoC: 首先 IoC 的目的是控制權的轉移,如原 PO 文章裡面原本是在 Employee 裡面 new Address,而採用 IoC 之後這樣的行為就轉移到外部來決定
爆
[心情] 婚後才發現自己崇尚自由看到版上討論這麼激烈有點嚇到我了~ 之所以發在女孩版而且分類為心情 是因為發文目的只是想抒發我的心情, 勸誡女孩們結婚前要想清楚婚後可能帶來的變化再做決定, 不要像我一樣太年輕把結婚想的太簡單就結婚了!!!!爆
[心情] 我已經不知道該怎麼辦了以下是我的回覆 因為編輯文章失敗,直接截圖文字 謝謝大家~ 目前懷孕28w38
Re: [爆卦] 呱吉回覆我說刪留言的文了我有個長期觀眾,每週固定幫我直播做timecode, 但他也是幾乎每次都會被系統刪除文章。 我都還要去垃圾桶裡救出來。 這件事情我的長期觀眾也都知道。 我已經盡量把所有被系統自動刪除的發文給取回了。爆
[心情] 我是不是真的可以遠離家裡了?版友們好 知道 WomanTalk 是很溫暖的版, 所以有點想詢問版友們的想法與意見 大家有遠離父母的經驗過嗎? 我最近真的很想搬出去了......爆
[問卦] 覺得自己爛透了如題啦 常常沒事就心情很差 做什麼都覺得自己很沒用 情緒常常上上下下的 前陣子嚴重到一直想去自殺 不過沒有去做任何危險動作爆
[問卦] 真的會有人用我以外的方式稱自己嗎?記得國中、高中都會學國文 然後有一堆詞會表示自己跟對方 像是你 以前古文會寫汝 有時候看布袋戲也會用汝稱呼 但現在時空環境不同根本不會有人這樣說爆
[寶寶] 寶寶取了我不喜歡的名字懷孕的時候我一直想幫寶寶取個好聽又有意義的名字,想了幾個 結果寶寶出生後公婆馬上衝去算命,不意外我想的都被打槍(我自己在算名字的網站排出 來明明都很高分),而算出來的名字我全都不愛。 算命師好像是公婆的朋友,給的字不是很過時,就是無意義的金木水火土,其中一組還有 「獃」(呆的古字)…。 公婆家的人從裡面選了一個他們最愛的,一開始我有弱弱的表達不喜歡,婆婆又再去給另 一個人算,但給的我們覺得又更差。 我不知道當時被什麼雷打到,覺得好吧,已經是裡面最不差的了,而且公婆對我很好,又 是給孩子的祝福,就同意了。80
[求助] 快暈船,但我還是在欺騙我自己二月底時我爸的朋友要介紹他鄰居的女兒給我認識,我跟我爸的朋友 (以下就簡稱老闆) 關係也算不錯,之前在他上海開的餐廳工作一陣子,也算是滿照顧我的。 他那麼熱心我也是不太好意思拒絕,想說就隨緣,女方OK那我也OK。 於是老闆就丟了女方的LINE要我加他,要我主動跟女方聯絡。我想說直接給一個LINE也太 隨便了吧?交友軟體至少還能知道女方的興趣、喜好。而我只從老闆知道女方也是宅宅,35
[求助] 是我的問題嗎?跟男友交往半年多 我24 在工作了 男友22 大學生 事情就發生在剛剛 今天上班很累