深入了解Spring控制反轉(zhuǎn)IOC原理
一、什么是Spring IOC容器
Spring是包含眾多工具的IoC容器,控制反轉(zhuǎn)即IoC,它有兩個(gè)核心的功能:
①將對(duì)象(Bean)存儲(chǔ)在容器(Spring)
②將對(duì)象(Bean)從容器(Spring)中取出來(lái)
【擴(kuò)展:將對(duì)象存放到容器中的好處】
將對(duì)象存儲(chǔ)在 IoC 容器相當(dāng)于將以后可能?的所有工具制作好都放到倉(cāng)庫(kù)中,需要的時(shí)候直接取就行了,用完再把它放回到倉(cāng)庫(kù)。而new 對(duì)象的方式相當(dāng)于,每次需要工具了,才現(xiàn)做,用完就扔掉了也不會(huì)保存,下次再用的時(shí)候還得重新做,這就是 IoC 容器和普通程序開(kāi)發(fā)的區(qū)別
二、IOC有哪些優(yōu)點(diǎn)
IOC 或 依賴(lài)注入把應(yīng)用的代碼量降到最低
它使應(yīng)用容易測(cè)試,單元測(cè)試不再需要單例和JNDI查找機(jī)制
最小的代價(jià)和最小的侵入性使松散耦合得以實(shí)現(xiàn)
IOC容器支持加載服務(wù)時(shí)的餓漢式初始化和懶加載
三、控制反轉(zhuǎn)(IOC)有什么作用
將創(chuàng)建對(duì)象的控制權(quán)交給Spring的IoC,以前需要程序員自己控制對(duì)象創(chuàng)建,現(xiàn)在交給Spring的IoC創(chuàng)建,如果需要使用需要通過(guò)DI(依賴(lài)注入)@Autowired自動(dòng)注入
解耦,由容器去維護(hù)具體的對(duì)象,降低耦合度
【擴(kuò)展:什么是解耦,代碼示例】
解耦指的是解決了代碼的耦合性,耦合性也可以換?種叫法叫程序相關(guān)性。這就好比我們打造?輛完整的汽車(chē),如果所有的配件都是自己造,那么當(dāng)客戶(hù)需求發(fā)生改變的時(shí)候,比如輪胎的尺寸不再是原來(lái)的尺寸了,那我們要自己動(dòng)手來(lái)改了,但如果我們是把輪胎外包出去,那么即使是輪胎的尺寸發(fā)生變變了,我們只需要向代理工廠(chǎng)下訂單就行了,我們自身身是不需要出力的
在傳統(tǒng)的代碼中對(duì)象創(chuàng)建順序是:Car -> Framework -> Bottom -> Tire
改進(jìn)之后解耦的代碼的對(duì)象創(chuàng)建順序是:Tire -> Bottom -> Framework -> Car

public class IocCarExample {
public static void main(String[] args) {
Tire tire = new Tire(20);
Bottom bottom = new Bottom(tire);
Framework framework = new Framework(bottom);
Car car = new Car(framework);
car.run();
}
//車(chē)類(lèi),把創(chuàng)建?類(lèi)的?式,改為注?傳遞的?式
static class Car {
private Framework framework;
public Car(Framework framework) {
this.framework = framework;
}
public void run() {
framework.init();
}
}
//車(chē)身類(lèi)
static class Framework {
private Bottom bottom;
public Framework(Bottom bottom) {
this.bottom = bottom;
}
public void init() {
bottom.init();
}
}四、IoC和DI有什么區(qū)別
IoC:控制反轉(zhuǎn),由主動(dòng)new產(chǎn)生對(duì)象(耦合過(guò)高)轉(zhuǎn)換成從外部提供對(duì)象,就是將對(duì)象的創(chuàng)建控制權(quán)從程序轉(zhuǎn)移到了外部
DI:依賴(lài)注入,就是在程序運(yùn)行期間,自動(dòng)的將一個(gè)對(duì)象從Spring拿出來(lái)給當(dāng)前類(lèi)使用
區(qū)別:
IoC 是“目標(biāo)”也是?種思想,而目標(biāo)和思想只是?種指導(dǎo)原則,而 DI 就是具體的實(shí)現(xiàn)
例如:比如說(shuō)我今天心情比較好,吃?頓好的犒勞犒勞自己,那么“吃?頓好的”是思想和目標(biāo)(是 IoC),但最后我是吃海底撈,這就是具體的實(shí)現(xiàn),就是 DI
五、Spring IoC的實(shí)現(xiàn)機(jī)制
1. 簡(jiǎn)單工廠(chǎng):通過(guò)一個(gè)方法傳入一個(gè)標(biāo)識(shí),生產(chǎn)對(duì)應(yīng)對(duì)象
工廠(chǎng)模式案例:
public static void main(String[] arge){
// 調(diào)用工廠(chǎng)方法,根據(jù)傳入?yún)?shù),返回一個(gè)對(duì)象
BaseService userService = Factory.getBean("user");
}
class Factory{
public static BaseService getBean(String beanName){
if("user".equals(beanName)){
return = new UserServiceImpl();
}
if("role".equals(beanName)){
return = new RoleServiceImpl();
}
}
}
2.反射:反射就是在工廠(chǎng)模式getBean()方法中通過(guò)反射的方式來(lái)創(chuàng)建Bean
class Factory {
public static Fruit getInstance(String ClassName) {
Fruit f=null;
try {
f=(Fruit)Class.forName(ClassName).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return f;
}
}
【擴(kuò)展:反射是什么,反射的實(shí)現(xiàn)原理】
反射機(jī)制是在運(yùn)行的狀態(tài),對(duì)于任何一個(gè)類(lèi),都能知道所有屬性和方法,對(duì)于任何一個(gè)對(duì)象都能調(diào)用任意方法屬性,所以反射就是將Java類(lèi)的各種成分映射成一個(gè)個(gè)對(duì)象
①通過(guò)Class類(lèi)的靜態(tài)方法:forName(String className)(常用)獲取Class對(duì)象
try {
Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必須是真實(shí)路徑,就是帶包名的類(lèi)路徑,包名.類(lèi)名
System.out.println(stuClass3 == stuClass2);//判斷三種方式是否獲取的是同一個(gè)Class對(duì)象
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
②通過(guò)反射獲取構(gòu)造方法并使用:
public class Student {
//---------------構(gòu)造方法-------------------
//(默認(rèn)的構(gòu)造方法)
Student(String str){
System.out.println("(默認(rèn))的構(gòu)造方法 s = " + str);
}
//無(wú)參構(gòu)造方法
public Student(){
System.out.println("調(diào)用了公有、無(wú)參構(gòu)造方法執(zhí)行了。。。");
}
//有一個(gè)參數(shù)的構(gòu)造方法
public Student(char name){
System.out.println("姓名:" + name);
}
//有多個(gè)參數(shù)的構(gòu)造方法
public Student(String name ,int age){
System.out.println("姓名:"+name+"年齡:"+ age);//這的執(zhí)行效率有問(wèn)題,以后解決。
}
//受保護(hù)的構(gòu)造方法
protected Student(boolean n){
System.out.println("受保護(hù)的構(gòu)造方法 n = " + n);
}
//私有構(gòu)造方法
private Student(int age){
System.out.println("私有的構(gòu)造方法 年齡:"+ age);
}
}六、IoC支持哪些功能
Spring 的 IoC 設(shè)計(jì)支持以下功能:
1.依賴(lài)注入
2.依賴(lài)檢查
3.自動(dòng)裝配
4.支持集合
5.指定初始化方法和銷(xiāo)毀方法
6.支持回調(diào)某些方法(但是需要實(shí)現(xiàn) Spring 接口,略有侵入)
其中,最重要的就是依賴(lài)注入,從 XML 的配置上說(shuō),即 ref 標(biāo)簽。對(duì)應(yīng) Spring RuntimeBeanReference 對(duì)象。
對(duì)于 IoC 來(lái)說(shuō),最重要的就是容器。容器管理著 Bean 的生命周期,控制著 Bean 的依賴(lài)注入
【擴(kuò)展:解釋Bean周期】下篇博客詳細(xì)介紹
七、BeanFactory和ApplicationContext有什么區(qū)別
首先創(chuàng)建Spring上下文的時(shí)候,會(huì)使用BeanFactory和ApplicationContext兩種方法
//先得到Spring上下文
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");//配置文件對(duì)應(yīng)
// 先得到 spring 獲取 bean 的對(duì)象
BeanFactory beanFactory =
new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
共同點(diǎn):BeanFactory和ApplicationContext是Spring的兩大核心接口,都可以當(dāng)做Spring的容器。其中ApplicationContext是BeanFactory的子接口
區(qū)別:
①繼承關(guān)系和功能:ApplicationContext是BeanFactory的子類(lèi),BeanFactory只是提供了基礎(chǔ)操作Bean的方法,ApplicationContext除了繼承了 BeanFactory 的所有功能之外,它還擁有獨(dú)特的特性,還添加了對(duì)國(guó)際化?持,資源訪(fǎng)問(wèn)?持等
②性能:ApplicationContext 是?次性加載并初始化所有的 Bean 對(duì)象,而 BeanFactory是需要那個(gè)才去加載那個(gè),因此更加輕量
八、ApplicationContext通常的實(shí)現(xiàn)是什么
FileSystemXmlApplicationContext :此容器從一個(gè)XML文件中加載beans的定義,XML Bean 配置文件的全路徑名必須提供給它的構(gòu)造函數(shù)
ClassPathXmlApplicationContext:此容器也從一個(gè)XML文件中加載beans的定義,這里,你需要正確設(shè)置classpath因?yàn)檫@個(gè)容器將在classpath里找bean配置
WebXmlApplicationContext:此容器加載一個(gè)XML文件,此文件定義了一個(gè)WEB應(yīng)用的所有bean
九、依賴(lài)注入的方式,構(gòu)造器依賴(lài)注入和 Setter方法注入的區(qū)別
依賴(lài)注入是時(shí)下最流行的IoC實(shí)現(xiàn)方式,依賴(lài)注入分為接口注入,Setter方法注入,和構(gòu)造器注入,三種方式。其中接口注入由于在靈活性和易用性比較差,現(xiàn)在從Spring4開(kāi)始已被廢棄
1.構(gòu)造器注入
將被依賴(lài)對(duì)象通過(guò)構(gòu)造函數(shù)的參數(shù)注入給依賴(lài)對(duì)象,并且在初始化對(duì)象的時(shí)候注入。優(yōu)點(diǎn):對(duì)象初始化完成后便可獲得可使用的對(duì)象。
缺點(diǎn):當(dāng)需要注入的對(duì)象很多時(shí),構(gòu)造器參數(shù)列表將會(huì)很長(zhǎng);不夠靈活。若有多種注入方式,每種方式只需注入指定幾個(gè)依賴(lài),那么就需要提供多個(gè)重載的構(gòu)造函數(shù),麻煩
2.setter方法注入
lOC Service Provider通過(guò)調(diào)用成員變量提供的setter函數(shù)將被依賴(lài)對(duì)象注入給依賴(lài)類(lèi)優(yōu)點(diǎn):靈活,可以選擇性地注入需要的對(duì)象
缺點(diǎn):依賴(lài)對(duì)象初始化完成后由于尚未注入被依賴(lài)對(duì)象,因此還不能使用
3.接口注入
依賴(lài)類(lèi)必須要實(shí)現(xiàn)指定的接口,然后實(shí)現(xiàn)該接口中的一個(gè)函數(shù),該函數(shù)就是用于依賴(lài)注入。該函數(shù)的參數(shù)就是要注入的對(duì)象
優(yōu)點(diǎn):接口注入中,接口的名字、函數(shù)的名字都不重要,只要保證函數(shù)的參數(shù)是要注入的對(duì)象類(lèi)型即可。缺點(diǎn):侵入行太強(qiáng),不建議使用
【擴(kuò)展:什么是侵入性?】
如果類(lèi)A要使用月別人提供的一個(gè)功能,若為了使用這功能,需要在自己的類(lèi)中增加額外的代碼,這就是侵入性
區(qū)別:

十、依賴(lài)注入的基本原則和優(yōu)點(diǎn)
依賴(lài)注入的基本原則:
應(yīng)用組件不應(yīng)該負(fù)責(zé)查找資源或者其他依賴(lài)的協(xié)作對(duì)象。配置對(duì)象的工作應(yīng)該由IoC容器負(fù)責(zé),“查找資源”的邏輯應(yīng)該從應(yīng)用組件的代碼中抽取出來(lái),交給IoC容器負(fù)責(zé)。容器全權(quán)負(fù)責(zé)組件的裝配,它會(huì)把符合依賴(lài)關(guān)系的對(duì)象通過(guò)屬性(JavaBean中的setter)或者是構(gòu)造器傳遞給需要的對(duì)象
優(yōu)勢(shì):
①查找定位操作與應(yīng)用代碼完全無(wú)關(guān)
②不依賴(lài)于容器的API,可以很容易地在任何容器以外使用應(yīng)用對(duì)象
③不需要特殊的接口,絕大多數(shù)對(duì)象可以做到完全不必依賴(lài)容器
以上就是深入了解Spring控制反轉(zhuǎn)IOC原理的詳細(xì)內(nèi)容,更多關(guān)于Spring控制反轉(zhuǎn)IOC的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java編譯時(shí)類(lèi)型與運(yùn)行時(shí)類(lèi)型
這篇文章主要介紹了Java編譯時(shí)類(lèi)型與運(yùn)行時(shí)類(lèi)型,文章以父類(lèi)BaseClass和子類(lèi)SubClass為例展開(kāi)對(duì)主題的探討,具有一的?參考價(jià)值,需要的小伙伴可以參考一下2022-03-03
java阻塞隊(duì)列BlockingQueue詳細(xì)解讀
這篇文章主要介紹了java阻塞隊(duì)列BlockingQueue詳細(xì)解讀,在新增的Concurrent包中,BlockingQueue很好的解決了多線(xiàn)程中,如何高效安全“傳輸”數(shù)據(jù)的問(wèn)題,通過(guò)這些高效并且線(xiàn)程安全的隊(duì)列類(lèi),為我們快速搭建高質(zhì)量的多線(xiàn)程程序帶來(lái)極大的便利,需要的朋友可以參考下2023-10-10
在SpringBoot項(xiàng)目中使用Java8函數(shù)式接口的方法示例
在Spring Boot項(xiàng)目中,Java 8 的函數(shù)式接口廣泛用于實(shí)現(xiàn)各種功能,如自定義配置、數(shù)據(jù)處理等,函數(shù)式接口在Spring Boot中非常有用,本文展示了在SpringBoot項(xiàng)目中使用Java8的函數(shù)式接口的方法示例,需要的朋友可以參考下2024-03-03
Java線(xiàn)程實(shí)現(xiàn)的兩種方式解析
這篇文章主要介紹了Java線(xiàn)程實(shí)現(xiàn)的兩種方式解析,注意在構(gòu)造器中啟動(dòng)這個(gè)線(xiàn)程的話(huà),很容易造成this逃逸的問(wèn)題,這是要注意的,這是通過(guò)直接集成thread來(lái)成為線(xiàn)程,同時(shí)在這種情況下,你可以通過(guò)調(diào)用合適的方法來(lái),需要的朋友可以參考下2024-01-01
Java開(kāi)發(fā)環(huán)境配置教程(win7 64bit)
這篇文章主要為大家詳細(xì)介紹了win7 64bit下Java開(kāi)發(fā)環(huán)境的配置教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
不到十行實(shí)現(xiàn)javaCV圖片OCR文字識(shí)別
識(shí)別圖片中的文字,會(huì)省很多時(shí)間,本文介紹了javaCV圖片OCR文字識(shí)別,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05

