Java Spring 控制反轉(zhuǎn)(IOC)容器詳解
IoC 容器是 Spring 的核心,也可以稱為 Spring 容器。Spring 通過(guò) IoC 容器來(lái)管理對(duì)象的實(shí)例化和初始化,以及對(duì)象從創(chuàng)建到銷毀的整個(gè)生命周期。
Spring 中使用的對(duì)象都由 IoC 容器管理,不需要我們手動(dòng)使用 new 運(yùn)算符創(chuàng)建對(duì)象。由 IoC 容器管理的對(duì)象稱為 Spring Bean,Spring Bean 就是 Java 對(duì)象,和使用 new 運(yùn)算符創(chuàng)建的對(duì)象沒(méi)有區(qū)別。
Spring 通過(guò)讀取 XML 或 Java 注解中的信息來(lái)獲取哪些對(duì)象需要實(shí)例化。
Spring 提供 2 種不同類型的 IoC 容器,即 BeanFactory 和 ApplicationContext 容器。
什么是容器?
容器是一種為某種特定組件的運(yùn)行提供必要支持的一個(gè)軟件環(huán)境。例如,Tomcat就是一個(gè)Servlet容器,它可以為Servlet的運(yùn)行提供運(yùn)行環(huán)境。類似Docker這樣的軟件也是一個(gè)容器,它提供了必要的Linux環(huán)境以便運(yùn)行一個(gè)特定的Linux進(jìn)程。
通常來(lái)說(shuō),使用容器運(yùn)行組件,除了提供一個(gè)組件運(yùn)行環(huán)境之外,容器還提供了許多底層服務(wù)。例如,Servlet容器底層實(shí)現(xiàn)了TCP連接,解析HTTP協(xié)議等非常復(fù)雜的服務(wù),如果沒(méi)有容器來(lái)提供這些服務(wù),我們就無(wú)法編寫(xiě)像Servlet這樣代碼簡(jiǎn)單,功能強(qiáng)大的組件。早期的JavaEE服務(wù)器提供的EJB容器最重要的功能就是通過(guò)聲明式事務(wù)服務(wù),使得EJB組件的開(kāi)發(fā)人員不必自己編寫(xiě)冗長(zhǎng)的事務(wù)處理代碼,所以極大地簡(jiǎn)化了事務(wù)處理。
無(wú)侵入容器
在設(shè)計(jì)上,Spring的IoC容器是一個(gè)高度可擴(kuò)展的無(wú)侵入容器。所謂無(wú)侵入,是指應(yīng)用程序的組件無(wú)需實(shí)現(xiàn)Spring的特定接口,或者說(shuō),組件根本不知道自己在Spring的容器中運(yùn)行。這種無(wú)侵入的設(shè)計(jì)有以下好處:
1.應(yīng)用程序組件既可以在Spring的IoC容器中運(yùn)行,也可以自己編寫(xiě)代碼自行組裝配置;
2.測(cè)試的時(shí)候并不依賴Spring容器,可單獨(dú)進(jìn)行測(cè)試,大大提高了開(kāi)發(fā)效率。
IOC控制反轉(zhuǎn)
Spring提供的容器又稱為IoC容器,什么是IoC?
Ioc—Inversion of Control,即“控制反轉(zhuǎn)”,不是什么技術(shù),是一個(gè)概念,是一種思想。指將傳統(tǒng)上由程序代 碼直接操控的對(duì)象調(diào)用權(quán)交給容器,通過(guò)容器來(lái)實(shí)現(xiàn)對(duì)象的裝配和管理??刂品崔D(zhuǎn)就是對(duì)對(duì)象控制權(quán)的轉(zhuǎn)移,從程序代碼本身反轉(zhuǎn)到了外部容器。通過(guò)容器實(shí)現(xiàn)對(duì)象的裝配和管理。通俗點(diǎn)講,將對(duì)象的創(chuàng)建權(quán)交給spring,我們需要new對(duì)象,則由spring幫我們創(chuàng)建,然后供我們使用。
那么必然的我們需要?jiǎng)?chuàng)建一個(gè)容器,同時(shí)需要一種描述來(lái)讓容器知道需要?jiǎng)?chuàng)建的對(duì)象與對(duì)象的關(guān)系。這個(gè)描述最具體表現(xiàn)就是我們可配置的文件。IoC的實(shí)質(zhì)是如何管理對(duì)象,傳統(tǒng)意義上我們使用new方式來(lái)創(chuàng)建對(duì)象,但在企業(yè)應(yīng)用開(kāi)發(fā)的過(guò)程中,大量的對(duì)象創(chuàng)建都在程序中維護(hù)很容易造成資源浪費(fèi),并且不利于程序的擴(kuò)展。
其實(shí)現(xiàn)方式多種多樣。當(dāng)前比較流行的實(shí)現(xiàn)方式是依賴 注入。應(yīng)用廣泛。
依賴:classA 類中含有 classB 的實(shí)例,在 classA 中調(diào)用 classB 的方法完成功能,即 classA 對(duì) classB 有依賴。
IOC理論推導(dǎo)
傳統(tǒng)應(yīng)用程序開(kāi)發(fā)的弊端
在理解IoC之前,我們先看看通常的Java組件是如何協(xié)作的。
我們先用我們?cè)瓉?lái)的方式寫(xiě)一段代碼 .
1、先寫(xiě)一個(gè)UserDao接口

2、再去寫(xiě)Dao的實(shí)現(xiàn)類
public class UserDaoOneImpl implements UserDao {
@Override
public void getUser() {
System.out.println("One獲取用戶數(shù)據(jù)");
}
}
3、然后去寫(xiě)UserService的接口

4、最后寫(xiě)Service的實(shí)現(xiàn)類

5、測(cè)試一下

6、再回到UserDao接口

把Userdao的實(shí)現(xiàn)類增加一個(gè) .
public class UserDaoMyTwoImpl implements UserDao {
@Override
public void getUser() {
System.out.println("Two獲取用戶數(shù)據(jù)");
}
}
7、我們就需要去service實(shí)現(xiàn)類里面修改對(duì)應(yīng)的實(shí)現(xiàn)
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoTwo();
@Override
public void getUser() {
userDao.getUser();
}
}
在假設(shè), 我們?cè)僭黾右粋€(gè)Userdao的實(shí)現(xiàn)類 .
public class UserDaoThreeImpl implements UserDao {
@Override
public void getUser() {
System.out.println("Three獲取用戶數(shù)據(jù)");
}
}
那么我們要使用Three , 又需要去service實(shí)現(xiàn)類里面修改對(duì)應(yīng)的實(shí)現(xiàn) . 假設(shè)我們的這種需求非常大 , 這種方式就根本不適用了, 甚至反人類對(duì)吧 , 每次變動(dòng) , 都需要修改大量代碼 . 這種設(shè)計(jì)的耦合性太高了, 牽一發(fā)而動(dòng)全身 .
“注入”機(jī)制
注入應(yīng)用程序某個(gè)對(duì)象,應(yīng)用程序依賴的對(duì)象
依賴注入可以通過(guò)set()方法實(shí)現(xiàn)。但依賴注入也可以通過(guò)構(gòu)造方法實(shí)現(xiàn)。Spring的IoC容器同時(shí)支持屬性注入和構(gòu)造方法注入,并允許混合使用。
我們可以在需要用到他的地方 , 不去實(shí)現(xiàn)它 , 而是留出一個(gè)接口 , 利用set , 我們?nèi)ゴa里修改下 .

@Test
public void test(){
UserServiceImpl service = new UserServiceImpl();
service.setUserDao( new UserDaoTwoImpl() );
service.getUser();
//那我們現(xiàn)在又想添加Three去實(shí)現(xiàn)呢
service.setUserDao( new UserDaoThreeImpl() );
service.getUser();
}
以前所有東西都是由程序去進(jìn)行控制創(chuàng)建 , 而現(xiàn)在是由我們自行控制創(chuàng)建對(duì)象 , 把主動(dòng)權(quán)交給了調(diào)用者 . 程序不用去管怎么創(chuàng)建,怎么實(shí)現(xiàn)了 . 它只負(fù)責(zé)提供一個(gè)接口 .
這種思想 , 從本質(zhì)上解決了問(wèn)題 , 我們程序員不再去管理對(duì)象的創(chuàng)建了 , 更多的去關(guān)注業(yè)務(wù)的實(shí)現(xiàn) . 耦合性大大降低 . 這也就是IOC的原型 !
小結(jié)
傳統(tǒng)程序設(shè)計(jì)如圖,都是主動(dòng)去創(chuàng)建相關(guān)對(duì)象然后再組合起來(lái):

沒(méi)有什么是加一層解決不了的

當(dāng)有了IoC/DI的容器后,在客戶端類中不再主動(dòng)去創(chuàng)建這些對(duì)象了
IOC本質(zhì)
IoC是Spring框架的核心內(nèi)容,使用多種方式完美的實(shí)現(xiàn)了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置實(shí)現(xiàn)IoC。
Spring容器在初始化時(shí)先讀取配置文件,根據(jù)配置文件或元數(shù)據(jù)創(chuàng)建與組織對(duì)象存入容器中,程序使用時(shí)再?gòu)腎oc容器中取出需要的對(duì)象。

控制反轉(zhuǎn)是一種通過(guò)描述(XML或注解)并通過(guò)第三方去生產(chǎn)或獲取特定對(duì)象的方式。在Spring中實(shí)現(xiàn)控制反轉(zhuǎn)的是IoC容器,其實(shí)現(xiàn)方法是依賴注入(Dependency Injection,DI)。
DI(依賴注入)
IoC的一個(gè)重點(diǎn)是在系統(tǒng)運(yùn)行中,動(dòng)態(tài)的向某個(gè)對(duì)象提供它所需要的其他對(duì)象。這一點(diǎn)是通過(guò)DI(Dependency Injection,依賴注入)來(lái)實(shí)現(xiàn)的。 比如對(duì)象A需要操作數(shù)據(jù)庫(kù),以前我們總是要在A中自己編寫(xiě)代碼來(lái)獲得一個(gè)Connection對(duì)象,有了 spring我們就只需要告訴spring,A中需要一個(gè)Connection,至于這個(gè)Connection怎么構(gòu)造,何時(shí)構(gòu)造,A不需要知道。在系統(tǒng)運(yùn)行時(shí),spring會(huì)在適當(dāng)?shù)臅r(shí)候制造一個(gè)Connection,然后像打針一樣,注射到A當(dāng)中,這樣就完成了對(duì)各個(gè)對(duì)象之間關(guān)系的控制。A需要依賴 Connection才能正常運(yùn)行,而這個(gè)Connection是由spring注入到A中的,依賴注入的名字就這么來(lái)的。那么DI是如何實(shí)現(xiàn)的呢? Java 1.3之后一個(gè)重要特征是反射(reflection),它允許程序在運(yùn)行的時(shí)候動(dòng)態(tài)的生成對(duì)象、執(zhí)行對(duì)象的方法、改變對(duì)象的屬性,spring就是通過(guò)反射來(lái)實(shí)現(xiàn)注入的。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
使用java實(shí)現(xiàn)備份和恢復(fù)SQLServer表數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了如何使用java實(shí)現(xiàn)備份和恢復(fù)SQLServer表數(shù)據(jù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01
java網(wǎng)上圖書(shū)商城(3)Book模塊
這篇文章主要為大家詳細(xì)介紹了java網(wǎng)上圖書(shū)商城,Book模塊,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
springboot如何通過(guò)URL方式訪問(wèn)外部資源
這篇文章主要介紹了springboot如何通過(guò)URL方式訪問(wèn)外部資源,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
JMeter 實(shí)現(xiàn)Java請(qǐng)求步驟及原理詳解
這篇文章主要介紹了JMeter 實(shí)現(xiàn)Java請(qǐng)求步驟及原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
Nacos設(shè)置為windows自啟動(dòng)服務(wù)的步驟詳解
這篇文章給大家介紹了Nacos設(shè)置為windows自啟動(dòng)服務(wù)的操作步驟,文中通過(guò)代碼示例和圖文結(jié)合講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-12-12
spring?IOC容器的Bean管理XML自動(dòng)裝配過(guò)程
這篇文章主要為大家介紹了spring?IOC容器Bean管理基于XML的自動(dòng)裝配過(guò)程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
java 下執(zhí)行mysql 批量插入的幾種方法及用時(shí)
java 下執(zhí)行mysql 批量插入的幾種方法及用時(shí),1000次插入方法的比較。2013-04-04
Spring Boot整合Mybatis Plus和Swagger2的教程詳解
這篇文章主要介紹了Spring Boot整合Mybatis Plus和Swagger2的教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02

