Spring IOC與DI核心深入理解
深入理解IOC思想
spring本質(zhì)就在于將對象全部交由給spring容器創(chuàng)建和管理,由容器控制對象的整個生命周期、核心就是IOC控制反轉(zhuǎn)和AOP面向切面編程
先說IOC
IOC是一種設計思想,叫做控制反轉(zhuǎn)。本質(zhì)就是通過Spring來負責對象的生命周期以及對象間的關(guān)系。在面向?qū)ο蟮拈_發(fā)過程中,我們程序中的各個對象往往會存在各種各樣的依賴關(guān)系,因此耦合度極高,一旦修改其中一個類信息就會牽扯到很多相關(guān)類需要修改。那么為了降低這種耦合度IOC指出引用第三方容器,也就是將所有對象的創(chuàng)建和管理交由第三方容器統(tǒng)一操作。這里的容器指的就是spring容器,我們需要將各個實現(xiàn)類映射到spring容器中的bean。
看了網(wǎng)上一些大佬的理解,針對IOC主要兩個問題,IOC是誰控制誰,被反轉(zhuǎn)的是什么?Spring容器控制了對象,創(chuàng)建對象的主動權(quán)從程序編碼反轉(zhuǎn)給了spring容器。扯到IOC就不得不提DI依賴注入,
- 應用程序依賴于IOC容器
- 通過DI,程序可以獲得所需的依賴資源比如一個對象或常量數(shù)據(jù)
- IOC容器將依賴對象注入到程序中
這個過程就體現(xiàn)出了IOC思想。
面試回答:什么是IOC?傳統(tǒng)的面向?qū)ο箝_發(fā)中需要我們手動編碼通過new關(guān)鍵字創(chuàng)建對象并為對象裝配所需資源,而控制反轉(zhuǎn)則可以將創(chuàng)建對象的主動權(quán)交給第三方容器完成,程序變成被動的接收對象。我認為IOC主要牽扯到兩個問題就是誰控制誰,什么被反轉(zhuǎn)?首先控制就是由最初的程序控制對象反轉(zhuǎn)為由容器控制對象,被反轉(zhuǎn)的就是獲取依賴對象的方式
DI&IOC
一直覺得對于IOC的理解不夠深入,發(fā)現(xiàn)自己忽略了一個關(guān)鍵詞–>依賴對象,那么什么是依賴對象。對于依賴對象的定義我的理解是,兩個對象都有自己需要完成的工作,但是A對象的一些行為需要B對象協(xié)作完成,那么在這些協(xié)作完成的行為中A對象就可以被稱之為B對象的依賴對象。此時兩者的耦合度是較高的,因為一旦某一個對象發(fā)生變化將會影響到另一個對象
我們假設對象A需要去操作數(shù)據(jù)庫,那么A就會需要獲得Connection連接對象,在使用spring之前我們通過編碼new關(guān)鍵字獲取一個連接交給對象A,此時對象A與Connection就是存在一定的耦合性的。引入了spring容器之后,我們將Connection去注冊到容器當中然后Connection會由容器創(chuàng)建完成,當A需要的時候就丟給A去使用,不用去關(guān)心Connection怎么創(chuàng)建,實現(xiàn)解耦。Connection就是對象A的一個依賴對象,但是在我看來,依賴對象并不僅僅代表一個對象,也可以是一個常量數(shù)據(jù)。我在整合mybatis和spring的時候,我終于體會到了解耦的感覺,之前在使用sqlSessionFactory創(chuàng)建SqlSession的過程中,首先要創(chuàng)建sqlSessionFactory然后通過它的openSession方法去獲取SqlSession實例,也就是說SqlSession依賴于SqlSessionFactory,下面看最初的寫法
{ private static SqlSessionFactory sqlSessionFactory; static { try { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { throw new RuntimeException(e); } } // 提供工廠方法 創(chuàng)建sqlSession實例 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }
上述代碼中,我們通過new創(chuàng)建SqlSessionFactoryBuilder,在調(diào)用它的build方法創(chuàng)建出了sqlSessionFactory,這之間就存在這依賴關(guān)系,也就是存在耦合。繼續(xù)往下看,我們直接編寫好一個方法用于獲取SqlSession實例,但是這個方法也是通過factory創(chuàng)建的。所以兩者之間同樣存在耦合關(guān)系。那么引入spring容器之后,我們利用第三方的容器,就可以實現(xiàn)兩者的解耦??聪铝衋pplicationContext的配置
<!-- 配置sqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="datasource"/> <!-- 綁定mybatis配置文件 --> <property name="configLocation" value="classpath:mybatis-config.xml"/> <!-- 映射器 注冊mapper.xml文件 --> <property name="mapperLocations" value="classpath:com/yuqu/dao/*.xml"/> </bean> <!-- 配置sqlsession --> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <!-- 只能選擇構(gòu)造器注入sqlSessionFactory 沒有SqlSessionTemplate提供set方法 --> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean>
看到了嗎,sqlSessionFactory被我們映射為容器中的bean,然后映射SqlSession的bean,然后通過注入的方式將sqlSessionFactory注入進sqlSession中,當在程序中需要獲取sqlSession的時候就不用再去管SqlSessionFactory是如何創(chuàng)建的。以此實現(xiàn)真正解耦的目的。同樣的我們可以將sqlSession去配置到其他的bean中
<bean id="userMapperImpl" class="com.yuqu.dao.UserMapperImpl"> <property name="sqlSession" ref="sqlSession"/> </bean>
這樣在需要獲取userMapperImpl對象的時候就不用再去創(chuàng)建sqlSession實例然后getMapper,只需要直接用spring去getBean即可獲取到,同樣也完成了解耦工作。
所以說,DI依賴注入就是實現(xiàn)IOC的一種方式。
關(guān)于AOP面向切面編程,可以參考這篇博客
到此這篇關(guān)于Spring IOC與DI核心深入理解的文章就介紹到這了,更多相關(guān)Spring IOC與DI內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot自定義MessageConverter與內(nèi)容協(xié)商管理器contentNegotiationManag
這篇文章主要介紹了SpringBoot自定義MessageConverter與內(nèi)容協(xié)商管理器contentNegotiationManager的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2022-10-10Java如何根據(jù)不同系統(tǒng)動態(tài)獲取換行符和盤分割符
這篇文章主要介紹了Java如何根據(jù)不同系統(tǒng)動態(tài)獲取換行符和盤分割符,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12Spring Boot整合QueryDSL的實現(xiàn)示例
這篇文章主要介紹了Spring Boot整合QueryDSL的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-09-09