控制反轉(Inversion of Control,英文縮寫爲IoC)是一個重要的面向對象編程的法則來削減計算機程序的耦合問題,也是輕量級的Spring框架的核心。 控制反轉還有一個名字叫作依賴注入(Dependency Injection)。簡稱DI。程序員
以上是來自於百度百科中關於IOC和DI的簡單介紹,從中咱們能夠看到ioc的主要做用是減小類與類之間的耦合程度,在spring中,ioc的表現爲類的實例化由本來程序員本身建立對象的動做轉爲由spring容器建立對象。web
在不使用IOC的狀況下,咱們實例化一個類spring
IEngine engine = new QiyouEngine();
在這個語句中咱們用到了IEngine接口和其實現類QiyouEngine,這樣這個類就須要引用這兩個類,若是須要改動實現類,則須要修改代碼,這就違反了面向對象設計中的」開閉原則「。想要解耦這段代碼,通常的解決可使用工廠模式對其解耦編程
1 public class Main{ 2 public static void main(String args[]){ 3 IEngine engine = EngineFactory.getEngine(); 4 engine.doSomething(); 5 } 6 } 7 8 9 public class EngineFactory{ 10 public static getEngine(){ 11 return new QiyouEngine(); 12 } 13 }
若是再進一步,可使用工廠模式+配置文件+反射來實現session
好比咱們的配置文件叫config.property,裏面配置app
engine=com.example.QiyouEngine;框架
在工廠中咱們就能夠修改爲ide
1 public class EngineFactory { 2 3 public static IEngine getEngine() throws Exception{ 4 // 讀取配置文件 5 Properties prop = new Properties(); 6 String rootPath = System.getProperty( " user.dir " ); 7 File f = new File(rootPath + File.separator + " config " + File.separator + " config.property " ); 8 InputStream in = new BufferedInputStream( new FileInputStream(f)); 9 prop.load(in); 10 String className = prop.getProperty( " engine " ); 11 12 // 根據反射得到類 13 IEngine engine = (IEngine) Class.forName(className).newInstance(); 14 return engine; 15 } 16 }
這樣只要修改配置文件中的實現類名就能夠修改程序中的實現類,從而達到不用修改代碼的目的。學習
和上面的例子類似,spring也有着本身的配置文件。this
這裏我在src目錄下建立了一個applicationContext.xml配置文件,其內容是
1 <? xml version="1.0" encoding="UTF-8" ?> 2 < beans xmlns ="http://www.springframework.org/schema/beans" 3 xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation ="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans.xsd" > 6 7 < bean id ="engine" class ="com.demo.spring.car.QiyouEngine" > 8 </ bean > 9 </ beans >
在代碼中咱們能夠這麼寫:
1 public static void main( String[] args ) 2 { 3 ApplicationContext context = new ClassPathXmlApplicationContext( " applicationContext.xml " ); 4 IEngine engine = (IEngine) context.getBean( " engine " ); 5 engine.doSomething(); 6 }
這和剛剛的效果是同樣的。
若是你們在找IOC的時候通常都會伴隨着DI這個詞,在spring中,ioc和di是緊密聯繫的,下面咱們演示一下DI是什麼樣子的。
如今有一個類叫QiyouEngine,其中有個屬性是發動機的排量cc,若是通常的寫法,咱們會在對象建立後經過調用set方法,把值塞到對象中,在spring中能夠在配置文件中實現。咱們修改一下剛剛xml文件在engine bean中添加屬性:
< bean id ="engine" class ="com.demo.spring.car.QiyouEngine" > < property name ="cc" value ="2.0" ></ property > </ bean >
在代碼中咱們加入cc成員變量,併爲其添加set的方法
1 public class QiyouEngine implements IEngine { 2 3 private String cc; // 排量 4 5 public String getCc() { 6 return cc; 7 } 8 9 public void setCc(String cc) { 10 this .cc = cc; 11 } 12 13 public void description() { 14 System.out.println( " 我是汽油發動機\n " + this .toString()); 15 } 16 17 @Override 18 public String toString() { 19 return " QiyouEngine [cc= " + cc + " ] " ; 20 } 21 22 }
在建立完對象後,spring會自動調用set的方法把值塞入對象中。
再運行一邊Main類,結果以下
固然,咱們注入的不知是常量,也能夠注入其餘的類。
好比如今咱們有一個類叫Car,它有兩個屬性,一個是name,另外一個是engine,咱們要作的就是把剛剛的QiyouEngine注入到Car中
< bean id ="car" class ="com.demo.spring.car.Car" > < property name ="name" value ="寶馬" ></ property > < property name ="engine" ref ="engine" ></ property > </ bean >
圖片中能夠看到engine用的是ref,而不是value,這個就是引用其餘類的關鍵
main類咱們修改一下,直接得到car類
public static void main( String[] args ) { ApplicationContext context = new ClassPathXmlApplicationContext( " applicationContext.xml " ); Car car = (Car) context.getBean( " car " ); System.out.println(car); }
Car類的定義
public class Car { private IEngine engine; private String name; public String getName() { return name; } public void setName(String name) { this .name = name; } public IEngine getEngine() { return engine; } public void setEngine(IEngine engine) { this .engine = engine; } @Override public String toString() { return " Car [engine= " + engine + " , name= " + name + " ] " ; } }
運行結果:
在bean標籤裏其實還有個屬性scope,這個屬性能夠說是標識這個經過spring ioc獲取的類的生命週期,其默認值是單例(Singleton),不過咱們執行多少次context.getBean(「engine」),得到的都是同一個對象,這個屬性一共有四個值
有關ioc和DI跟深刻的使用,待我學習完再和你們分享。