面試必備-如何回答你是怎麼理解spring IOC的?

一、 什麼是SpringIOC?

控制反轉(Inversion of Control,縮寫為IoC),是面向對象編程中的一種設計原則,可以用來減低計算機代碼之間的耦合度。其中最常見的方式叫做依賴注入(Dependency Injection,簡稱DI),還有一種方式叫“依賴查找”(Dependency Lookup)。通過控制反轉,對象在被創建的時候,由一個調控系統內所有對象的外界實體,將其所依賴的對象的引用傳遞給它。也可以說,依賴被注入到對象中。

舉個簡單的例子幫助理解一下

你想吃一份紅燒牛肉麵:

普通的做法:就是你去附近找一個飯館,然後再去這個飯館點一個這個面。

Ioc的做法:你在手機上外賣平臺搜索這個面,然後支付完成後,對應的飯館會通過送餐員直接送到你面前。

二、 SpringIOC的優點?

1. 解耦

究竟什麼是解耦呢?就是降低程序的耦合度,更方便的實現擴展。

其實好多同學還是有點懵的,說的多了反倒越想越迷,解耦其實可以用一句話來概括,就是通過中間者來取消調用者和被調用者的直接關係

比如你想租房子,你需要去網上搜租房信息,有合適的去看,如果不滿意,還要去找另一家去看,解耦的話,你只需要把你的需求給房產中介,他就會很方便的幫你帶你挑選適合你的房子。

2. 提高系統可插入、可測試、可修改等特性

因為文件可以通過xml或者註解統一進行配置,減少了很多不必要的代碼,所以測試和修改就變得更加的簡單。

三、 SpringIOC的缺點

1.因為反射的存在,導致性能降低,不過這點損耗不會太影響系統的運行。

2. 缺少IDE重構操作的支持,如果在Eclipse要對類改名,那麼你還需要去XML文件裡手工去改了,這似乎是所有XML方式的缺憾所在。

四、 SpringIOC的底層原理

1. 反射

1) 反射的概念

反射是Java語言的一個特性,它允許程序在運行時(注意不是編譯的時候)來進行自我檢查並且對內部的成員進行操作。例如它允許一個Java類獲取它所有的成員變量和方法並且顯示出來。

2) 反射機制的作用

1、在運行時判斷任意一個對象所屬的類。

2、在運行時獲取類的對象。

3、在運行時訪問java對象的屬性,方法,構造方法等。

2.

反射與工廠模式實現IOC

Spring中的IoC的實現原理就是工廠模式加反射機制。 我們首先看一下不用反射機制時的工廠模式:

interface fruit{ 
public abstract void eat();
}
class Apple implements fruit{
public void eat(){
System.out.println("Apple");
}
}
class Orange implements fruit{
public void eat(){
System.out.println("Orange");
}
}
class Factory{
public static fruit getInstance(String fruitName){
fruit f=null;
if("Apple".equals(fruitName)){
f=new Apple();
}
if("Orange".equals(fruitName)){
f=new Orange();
}
return f;
}
}
class hello{
public static void main(String[] a){
fruit f=Factory.getInstance("Orange");
f.eat();
}
}

上面寫法的缺點是當我們再添加一個子類的時候,就需要修改工廠類了。如果我們添加太多的子類的時候,改動就會很多。下面用反射機制實現工廠模式:

interface fruit{

public abstract void eat();

}

class Apple implements fruit{

public void eat(){

System.out.println("Apple");

}

}

class Orange implements fruit{

public void eat(){

System.out.println("Orange");

}

}

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;

}

}

class hello{

public static void main(String[] a){

fruit f=Factory.getInstance("Reflect.Apple");

if(f!=null){

f.eat();

}

}

}

現在就算我們添加任意多個子類的時候,工廠類都不需要修改。使用反射機制實現的工廠模式可以通過反射取得接口的實例,但是需要傳入完整的包和類名。而且用戶也無法知道一個接口有多少個可以使用的子類,所以我們通過屬性文件的形式配置所需要的子類。

下面編寫使用反射機制並結合屬性文件的工廠模式(即IoC)。首先創建一個fruit.properties的資源文件:

apple=Reflect.Appleorange=Reflect.Orange

然後編寫主類代碼:

interface fruit{

public abstract void eat();

}

class Apple implements fruit{

public void eat(){

System.out.println("Apple");

}

}

class Orange implements fruit{

public void eat(){

System.out.println("Orange");

}

}

//操作屬性文件類

class init{

public static Properties getPro() throws FileNotFoundException, IOException{

Properties pro=new Properties();

File f=new File("fruit.properties");

if(f.exists()){

pro.load(new FileInputStream(f));

}else{

pro.setProperty("apple", "Reflect.Apple");

pro.setProperty("orange", "Reflect.Orange");

pro.store(new FileOutputStream(f), "FRUIT CLASS");

}

return pro;

}

}

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;

}

}

class hello{

public static void main(String[] a) throws FileNotFoundException, IOException{

Properties pro=init.getPro();

fruit f=Factory.getInstance(pro.getProperty("apple"));

if(f!=null){

f.eat();

}

}

}

運行結果:Apple

五、 SpringIOC三種注入方式

1.接口注入:

接口注入模式因為具備侵入性,它要求組件必須與特定的接口相關聯,因此並不被看好,實際使用有限。

2.Setter 注入:

對於習慣了傳統 javabean 開發的程序員,通過 setter 方法設定依賴關係更加直觀。

如果依賴關係較為複雜,那麼構造子注入模式的構造函數也會相當龐大,而此時設值注入模式則更為簡潔。

如果用到了第三方類庫,可能要求我們的組件提供一個默認的構造函數,此時構造子注入模式也不適用。

3。構造器注入:

在構造期間完成一個完整的、合法的對象。

所有依賴關係在構造函數中集中呈現。

依賴關係在構造時由容器一次性設定,組件被創建之後一直處於相對“不變”的穩定狀態。

只有組件的創建者關心其內部依賴關係,對調用者而言,該依賴關係處於“黑盒”之中。

面試必備-如何回答你是怎麼理解spring IOC的?

-------END-------

本文參考了許多大牛的精華,如果覺的還不錯的話,可以支持一下。


分享到:


相關文章: