一、在傳統的程序設計中,調用親自建立被調用者的實例,即由程序控制「對象之間的依賴關係」,這種方式的耦合度比較高;控制反轉就是將由程序控制的「對象間的依賴關係」轉交給Ioc容器來進行控制,被調用者的實例建立工做再也不是調用者完成, 大大下降了調用者和被調用者之間的關係。Ioc(inversion of control:控制反轉)和Di(dependency Injection:依賴注入) 是相同的概念。
二、實現依賴注入的方式: 2.一、屬性注入: //bean類 被關聯 package com.liu.spring; public class RefBean { private String meg; public String getMeg() { return meg; } public void setMeg(String meg) { this.meg = meg; } } //bean 將關聯RefBean類 package com.liu.spring; public class MessageBean { private String message; private RefBean refBean;//關聯的RefBean類 public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public RefBean getRefBean() { return refBean; } public void setRefBean(RefBean refBean) { this.refBean = refBean; } } //配置文件 <beans> <!-- 配置文件 1.先配置類爲RefBean --> <bean id="refBean" class="com.liu.spring.RefBean"> <property name="meg"> <value>我是屬性注入方式實現的(我在RefBean類中)</value> </property> </bean> <!-- 二、再來配置類 MessageBean --> <bean id="messageBean" class="com.liu.spring.MessageBean"> <property name="message"> <value>Spring框架(我是在MessageBean類中)</value> </property> <!-- 加入另外一個bean --> <property name="refBean"> <ref local="refBean"/> </property> </bean> </beans> //測試類 package com.liu.action; public class Action_01 { public static void main(String[] args) { //加載配置文件 ClassPathResource resource=new ClassPathResource("applicationContext.xml"); //建立bean工廠 BeanFactory factory=new XmlBeanFactory(resource); //獲取對用的實例(就避免的new對象) MessageBean message=(MessageBean) factory.getBean("messageBean"); //打印結果 System.out.println(message.getMessage()+","+message.getRefBean().getMeg()); } } //最終的結果是 Spring框架(我是在MessageBean類中),我是屬性注入方式實現的(我在RefBean類中)
2.二、構造方法注入: 注:只需在被關聯的類中寫好構造函數,在配置文件之中寫好配置文件就行 //配置文件寫法 <bean id="messageBean" class="com.liu.spring.MessageBean"> <!--- 構造函數注入的關鍵標籤 ---> <constructor-arg index="0"> <value>Spring框架(我是在MessageBean類中)</value> </constructor-arg> <constructor-arg index="1"> <!-- 引用以外的bean --> <ref local="refBean"/> </constructor-arg> </bean> <!-- 被關聯的bean類---> <bean id="refBean" class="com.liu.spring.RefBean"> <property name="meg"> <value>我是屬性注入方式實現的(我在RefBean類中)</value> </property> </bean> 2.三、構造注入須知: 爲了不如今的配置文件的歧義而引發的張冠李戴,在bean中存在多個構造函數時,使用顯示指定index和type屬性 比較直觀。 2.四、屬性注入和構造注入的比較: 2.4.一、屬性注入的特色是不須要知道屬性的類型,可是必須知道屬性的名稱;使用set()方法實現依賴注入 2.4.二、構造函數注入的特色是不須要知道參數的名稱,不須要知道set(),可是必須知道參數的序號和類型,必須定義包含不一樣參數 的構造函數。 2.4.三、構造函數注入和屬性注入方式各有優缺點。 三、循環依賴問題: 3.一、什麼是循環依賴: spring容器可以順利實例化以構造函數注入的方式配置的Bean有一個前提:Bean引用的構造函數入參引用的對象必須已近準備就緒。因爲這種機制,若是兩個bean都採用構造函數注入,並且都是經過構造函數入參引用對方,就會發生死鎖,就是依賴循環。 實體類以下: //Boss類 package com.liu.spring; public class Boss { private String name; private Car car; public String getName() { return name; } public void setName(String name) { this.name = name; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } //構造函數 public Boss(String name, Car car) { super(); this.name = name; this.car = car; } } //car類 package com.liu.spring; public class Car { private String brand; private Boss boss; public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public Boss getBoss() { return boss; } public void setBoss(Boss boss) { this.boss = boss; } //構造函數 public Car(String brand, Boss boss) { super(); this.brand = brand; this.boss = boss; } } //配置文件 <!-- 循環依賴問題的配置文件以下 (錯) --> <bean id="car" class="com.liu.spring.Car"><!-- car類 --> <constructor-arg> <value>我是勞斯萊斯(來之car類)</value> </constructor-arg> <constructor-arg> <ref local="boss"/><!-- 引用boss --> </constructor-arg> </bean> <bean id="boss" class="com.liu.spring.Boss"> <constructor-arg> <value>我是劉明(來之boss類)</value> </constructor-arg> <constructor-arg> <ref local="car"/><!-- 引用car --> </constructor-arg> </bean> 異常爲:Exception in thread "main" org.springframework.beans.factory.BeanCreationException: 3.二、循環依賴解決方法(配置文件使用屬性注入) <!-- 循環依賴問題的配置文件以下 (正確) --> <bean id="car" class="com.liu.spring.Car"> <property name="brand"> <value>我是勞斯拉斯(來之car類)</value> </property> <property name="boss"> <ref local="boss"/> </property> </bean> <bean id="boss" class="com.liu.spring.Boss"> <property name="name"> <value>我是不知道(來之boss類)</value> </property> <property name="car"> <ref local="car"/> </property> </bean> ------測試類------------------ //加載配置文件 ClassPathResource resource=new ClassPathResource("applicationContext.xml"); //建立bean工廠 BeanFactory factory=new XmlBeanFactory(resource); //得到對應的實體類 Car car=(Car) factory.getBean("car"); Boss boss=(Boss) factory.getBean("boss"); System.out.println(car.getBrand()+"========"+car.getBoss().getName()); System.out.println(boss.getName()+"======="+boss.getCar().getBrand()); 最後的結果是: 我是勞斯拉斯(來之car類)========我是不知道(來之boss類) 我是不知道(來之boss類)=======我是勞斯拉斯(來之car類)