IOC學(xué)習(xí)筆記(上篇)
目錄
IOC容器的職責(zé)
Ioc容器的實(shí)現(xiàn)
傳統(tǒng)IoC容器的實(shí)現(xiàn)
依賴查找VS依賴注入
構(gòu)造器注入VS Setter注入
面試題
1. 什么是IOC?
2. 依賴查找和依賴注入的區(qū)別
3. Spring作為IOC容器有什么優(yōu)勢
學(xué)習(xí)視頻地址:https://time.geekbang.org/course/detail/100042601-184049
IOC容器的職責(zé)
依賴處理
依賴查找
依賴注入
生命周期管理
容器
托管的資源(Java Beans 或其他資源[1])
配置
容器
外部化配置
托管的資源(Java Beans或其他資源[1:1])
Ioc容器的實(shí)現(xiàn)
Java SE
Java Beans
Java ServiceLoader SPI[2]
JNDI(Java Naming and Directory Interface)
Java EE
EJB(Enterprise Java Beans)
Servlet
開源
Apache Avalon(http://avalon.apache.org/closed.html)
PicoContainer(http://picocontainer.com)
Google Guice(https://github.com/google/guice)
Spring Framework(https://spring.io/projects/spring-framework)
傳統(tǒng)IoC容器的實(shí)現(xiàn)
Java Beans作為IoC容器
特性
依賴查找
生命周期管理
配置元信息
事件
自定義
資源管理
持久化
規(guī)范
JavaBeans:https://www.oracle.com/technetwork/java/javase/tech/index-jsp-138795.html
BeanContext:https://docs.oracle.com/javase/8/docs/technotes/guides/beans/spec/beancontext.html
依賴查找VS依賴注入
優(yōu)劣對(duì)比

構(gòu)造器注入VS Setter注入
在選擇構(gòu)造器注入(Constructor Injection)和Setter注入(Setter Injection)之間,需要根據(jù)具體的情況來決定。 構(gòu)造器注入是通過類的構(gòu)造器來注入依賴對(duì)象,通常在創(chuàng)建對(duì)象的過程中完成注入。這種方式可以保證對(duì)象在創(chuàng)建完成后,其依賴關(guān)系已經(jīng)完全被注入,使得對(duì)象在使用時(shí)具備完整的狀態(tài)。構(gòu)造器注入也可以使對(duì)象的依賴關(guān)系更加明確,減少了對(duì)于Setter方法的依賴。 Setter注入是通過類的Setter方法來注入依賴對(duì)象,通常在對(duì)象創(chuàng)建后通過調(diào)用Setter方法來完成注入。這種方式可以在對(duì)象創(chuàng)建后動(dòng)態(tài)地修改其依賴關(guān)系,靈活性更高。Setter注入也可以支持可選的依賴,即某些依賴對(duì)象可以不注入而使用默認(rèn)值。 選擇構(gòu)造器注入還是Setter注入,可以考慮以下幾個(gè)方面:
對(duì)象的依賴關(guān)系是否必須要在創(chuàng)建時(shí)注入,還是可以在對(duì)象創(chuàng)建后進(jìn)行注入。如果依賴關(guān)系必須在創(chuàng)建時(shí)注入,那么構(gòu)造器注入是更合適的選擇;如果依賴關(guān)系可以在創(chuàng)建后動(dòng)態(tài)修改,那么可以考慮使用Setter注入。
對(duì)象的依賴關(guān)系是否是必需的,還是可選的。如果某些依賴是必需的,而且沒有合適的默認(rèn)值,那么構(gòu)造器注入可以確保這些依賴在創(chuàng)建時(shí)被注入;如果某些依賴是可選的,可以使用Setter注入,并提供默認(rèn)值。
對(duì)象的可測試性。構(gòu)造器注入可以使得對(duì)象的依賴關(guān)系更加明確,方便進(jìn)行單元測試,因?yàn)榭梢酝ㄟ^構(gòu)造器傳入模擬對(duì)象。而Setter注入在單元測試中可能需要通過反射等方式來設(shè)置依賴對(duì)象。
綜上所述,選擇構(gòu)造器注入還是Setter注入取決于具體的情況。如果依賴關(guān)系必須在創(chuàng)建時(shí)注入,而且是必需的,那么構(gòu)造器注入是更合適的選擇;如果依賴關(guān)系可以在創(chuàng)建后動(dòng)態(tài)修改,或者某些依賴是可選的,那么可以考慮使用Setter注入。同時(shí),還需要考慮對(duì)象的可測試性和代碼的可讀性等因素。
面試題
1. 什么是IOC?
IOC,全稱為Inversion of Control(控制反轉(zhuǎn)),是一種軟件設(shè)計(jì)原則和編程思想。它是面向?qū)ο缶幊蹋∣OP)中的一種設(shè)計(jì)模式,用于解耦對(duì)象間的依賴關(guān)系。 在傳統(tǒng)的程序設(shè)計(jì)中,對(duì)象之間的依賴關(guān)系由對(duì)象自身負(fù)責(zé)管理。例如,一個(gè)類在創(chuàng)建其他類的對(duì)象時(shí),需要直接調(diào)用其他類的構(gòu)造函數(shù)或方法來獲取所需的對(duì)象。這種方式使得類之間緊密耦合,難以進(jìn)行單元測試、代碼復(fù)用和替換等操作。 而IOC是一種反轉(zhuǎn)了對(duì)象創(chuàng)建和依賴關(guān)系管理的控制方式。在IOC中,對(duì)象的創(chuàng)建和依賴關(guān)系的管理由一個(gè)容器(Container)來負(fù)責(zé)。容器負(fù)責(zé)創(chuàng)建對(duì)象,并將依賴的對(duì)象注入到需要的地方。對(duì)象只需要定義自己所需的依賴,而不需要關(guān)心如何創(chuàng)建和管理這些依賴。這樣可以實(shí)現(xiàn)對(duì)象間的解耦,提高代碼的可維護(hù)性和可擴(kuò)展性。 IOC的核心思想是通過依賴注入(Dependency Injection)來實(shí)現(xiàn)對(duì)象之間的解耦。依賴注入是指將需要的依賴對(duì)象通過構(gòu)造器、Setter方法或其他方式注入到對(duì)象中,而不是由對(duì)象自己創(chuàng)建或獲取依賴對(duì)象。依賴注入可以通過配置文件、注解或自動(dòng)掃描等方式來實(shí)現(xiàn)。 IOC的好處包括:
解耦:IOC通過將對(duì)象的創(chuàng)建和依賴關(guān)系的管理交給容器來處理,使得對(duì)象之間的關(guān)系更加松散,減少了耦合。
可測試性:由于對(duì)象的依賴關(guān)系由容器注入,可以方便地進(jìn)行單元測試,通過替換依賴對(duì)象來進(jìn)行測試或模擬。
可擴(kuò)展性:在IOC中,可以通過配置文件或注解等方式來管理對(duì)象的依賴關(guān)系,使得系統(tǒng)更加靈活,能夠方便地進(jìn)行功能擴(kuò)展或替換。
常見的IOC框架包括Spring Framework、Google Guice等。這些框架提供了依賴注入的功能,可以幫助開發(fā)者實(shí)現(xiàn)IOC,并提供了其他的功能和工具來支持應(yīng)用程序的開發(fā)。 總結(jié)來說,IOC(控制反轉(zhuǎn))是一種軟件設(shè)計(jì)原則和編程思想,通過將對(duì)象的依賴關(guān)系的管理交給容器來處理,實(shí)現(xiàn)對(duì)象間的解耦。IOC的核心是依賴注入,將對(duì)象的依賴通過構(gòu)造器、Setter方法或其他方式注入到對(duì)象中。IOC可以提高代碼的可維護(hù)性、可測試性和可擴(kuò)展性。
2. 依賴查找和依賴注入的區(qū)別
依賴查找(Dependency Lookup)和依賴注入(Dependency Injection)是兩種不同的依賴關(guān)系管理方式。 依賴查找是指通過容器或上下文來查找所需的依賴對(duì)象。在依賴查找中,對(duì)象自己負(fù)責(zé)獲取它所依賴的對(duì)象,通常是通過容器提供的方法或API來獲取。例如,通過容器的getBean()方法來獲取所需的對(duì)象。 依賴注入是指將依賴對(duì)象通過構(gòu)造器、Setter方法或其他方式注入到對(duì)象中。在依賴注入中,對(duì)象不需要關(guān)心如何獲取依賴對(duì)象,而是通過注入的方式來獲取。注入可以通過配置文件、注解或自動(dòng)掃描等方式實(shí)現(xiàn)。 區(qū)別如下:
控制方式不同:依賴查找是由對(duì)象自己控制獲取依賴對(duì)象,而依賴注入是由容器控制將依賴對(duì)象注入到對(duì)象中。
依賴關(guān)系的表達(dá)方式不同:依賴查找需要在對(duì)象中顯式調(diào)用容器提供的方法來獲取依賴對(duì)象,而依賴注入是通過構(gòu)造器、Setter方法或其他方式將依賴對(duì)象注入到對(duì)象中。
對(duì)象的可測試性不同:依賴查找在單元測試中可能需要使用模擬對(duì)象等技術(shù)來替代真實(shí)的依賴對(duì)象,而依賴注入可以通過注入不同的依賴對(duì)象來進(jìn)行單元測試。
對(duì)象的依賴關(guān)系管理方式不同:依賴查找需要在每個(gè)對(duì)象中顯式獲取依賴對(duì)象,而依賴注入將依賴對(duì)象的管理交給容器來處理,對(duì)象只需要定義自己所需的依賴,不需要關(guān)心如何獲取和管理這些依賴。
綜上所述,依賴查找和依賴注入是兩種不同的依賴關(guān)系管理方式。依賴查找由對(duì)象自己負(fù)責(zé)獲取依賴對(duì)象,而依賴注入是由容器負(fù)責(zé)將依賴對(duì)象注入到對(duì)象中。選擇依賴查找還是依賴注入取決于具體的需求和設(shè)計(jì)風(fēng)格。依賴注入通常被認(rèn)為是更推薦的一種方式,因?yàn)樗軌驅(qū)崿F(xiàn)對(duì)象間的解耦,提高代碼的可維護(hù)性和可測試性。
3. Spring作為IOC容器有什么優(yōu)勢
Spring作為一個(gè)流行的IOC(控制反轉(zhuǎn))容器,具有以下優(yōu)勢:
松耦合:Spring實(shí)現(xiàn)了依賴注入(DI)機(jī)制,通過將對(duì)象的依賴關(guān)系交由容器管理,實(shí)現(xiàn)了對(duì)象間的松耦合。這使得代碼更容易理解、維護(hù)和擴(kuò)展,提高了系統(tǒng)的靈活性。
可測試性:Spring的依賴注入機(jī)制使得對(duì)象的依賴關(guān)系通過構(gòu)造器、Setter方法或其他方式注入,而不是直接在對(duì)象內(nèi)部創(chuàng)建或獲取依賴對(duì)象。這樣,在進(jìn)行單元測試時(shí),可以更方便地替換依賴對(duì)象,進(jìn)行集成測試和模塊測試。
面向接口編程:Spring鼓勵(lì)面向接口編程,通過接口來定義具體類的依賴關(guān)系。這種編程方式使得代碼更具擴(kuò)展性和可替換性,有利于實(shí)現(xiàn)多態(tài)和依賴倒置原則。
AOP支持:Spring提供了AOP(面向切面編程)的支持,通過配置和代理技術(shù),可以實(shí)現(xiàn)橫切關(guān)注點(diǎn)(例如事務(wù)管理、日志記錄等)的集中管理和復(fù)用。這樣,可以將業(yè)務(wù)邏輯與橫切關(guān)注點(diǎn)分離,提高代碼的重用性和可維護(hù)性。
生命周期管理:Spring容器管理對(duì)象的生命周期,可以在對(duì)象創(chuàng)建、初始化和銷毀時(shí)執(zhí)行相應(yīng)的操作。例如,通過配置初始化方法和銷毀方法,可以在對(duì)象創(chuàng)建和銷毀時(shí)執(zhí)行特定的邏輯。
配置靈活性:Spring采用基于XML、注解或Java配置的方式來進(jìn)行配置,使得配置更加靈活和可擴(kuò)展??梢愿鶕?jù)具體需求選擇合適的配置方式,方便地切換和修改配置,而不需要修改代碼。
集成豐富:Spring提供了豐富的集成支持,可以與各種開源和商業(yè)框架進(jìn)行集成,如Hibernate、MyBatis、Spring MVC等。這些集成支持簡化了開發(fā)過程,提高了開發(fā)效率和系統(tǒng)的整合能力。
總的來說,Spring作為一個(gè)IOC容器,通過依賴注入、面向接口編程、AOP支持、生命周期管理和靈活的配置等特性,提供了優(yōu)秀的開發(fā)框架和工具,使得開發(fā)者能夠更加專注于業(yè)務(wù)邏輯的實(shí)現(xiàn),提高了系統(tǒng)的可維護(hù)性、可測試性和可擴(kuò)展性。
比如監(jiān)聽器可以通過外部引入 ????
從JDK1.6版本開始引入 ??