當一個對象要調用另外一個對象時,通常是new一個被調用的對象,示例:app
class A{ide
private B b=new B();函數
public void test(){測試
b.say();this
}spa
}code
A類的對象依賴於B類對象,若是沒有B類對象,A類對象就不能正常工做,稱A依賴於B。xml
以上方式會增長類A與類B的耦合性,不利於項目後期的升級(擴展)、維護。對象
在Spring中,B類的實例(被調用者),再也不由A類(調用者)建立,而是由Spring容器建立,建立好之後,由Spring容器將B類的實例注入A類對象中,稱爲依賴注入(Dependency Injection,DI)。blog
本來是由A類主動建立B類對象(A類控制B類的建立),如今是Spring容器建立B類對象,注入A類對象中,A類被動接受Spring容器建立的B類實例,B類對象建立的控制權發生了反轉,因此又叫作控制反轉(Inversion of Control,IoC)。
依賴注入是一種優秀的解耦方式,由Spring容器負責控制類(Bean)之間的關係,下降了類之間的耦合。
由於Spring容器負責依賴注入(IoC),因此Spring容器也被稱爲Spring IoC容器。
依賴注入有2種實現方式:
經過主調類的setter()方法注入被調類的實例。一個參數即一個依賴對象。
一、分別寫2個接口
1 public interface Student { 2 public String getName(); 3 }
1 public interface Teacher { 2 public void say(); 3 }
二、分別寫2個實現類
1 public class BadStudent implements Student { 2 private String name; 3 4 public BadStudent(String name){ 5 this.name=name; 6 } 7 8 @Override 9 public String getName(){ 10 return name; 11 } 12 }
1 public class MathTeacher implements Teacher{ 2 private Student student; 3 4 //主調者的setter()方法,接受被調者實例 5 public void setStudent(Student student){ 6 this.student=student; 7 } 8 9 @Override 10 public void say() { 11 System.out.println(student.getName()+",叫家長來一下。"); 12 } 13 }
類與接口耦合。
三、在applicationContext.xml文件中配置Bean
1 <!-- 初始化BadStudent類的實例lisi--> 2 <bean name="lisi" class="beans.BadStudent"> 3 <constructor-arg value="李四" /> <!--向BadStudent的構造函數傳遞」李四「--> 4 </bean> 5 6 <!--配置依賴--> 7 <bean name="mathTeacher" class="beans.MathTeacher"> 8 <property name="student" ref="lisi" /> <!--name指定setter方法的形參,ref或者value指定實參:某個Bean的name--> 9 </bean>
<constructor-arg>元素向該Bean的構造函數傳遞實參,一個<constructor-arg>傳遞一個實參,一個<bean>可配置多個<constructor-arg>,根據傳遞的實參個數來調用相應的構造函數。constructor-arg即構造器參數。
實參值經過value或ref屬性來指定。value指定的是Java基礎類型的參數,ref即reference(引用),指定依賴的其它Bean。
可經過屬性index指定該value是第幾個參數,默認從0自動遞增。
<property>屬性指定setter方法的實參。一個<property>指定一個參數,一個<bean>可帶有多個<property>子元素。
name屬性指定setter方法中的某個形參,實參由value或ref指定。
若是實參是某個Bean的實例,用ref指定,值是該Bean的name屬性值。
若是實參是Java的基礎類型(整型、浮點型、String等),用value指定(放在引號中),Spring容器會自動根據name的指定形參的類型,將實參轉換爲相應的類型進行賦值。
四、寫一個測試類
1 public class Test { 2 public static void main(String[] args) { 3 ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml"); 4 MathTeacher mathTeacher=applicationContext.getBean("mathTeacher",MathTeacher.class); 5 mathTeacher.say(); 6 } 7 }
看到控制檯已經打印出了「李四,叫家長來一下。」。
經過構造函數注入。
一、上面的代碼,將MathTeacher類修改以下
1 public class MathTeacher implements Teacher{ 2 private Student student; 3 4 //主調者的構造方法 5 public MathTeacher(Student student){ 6 this.student=student; 7 } 8 9 @Override 10 public void say() { 11 System.out.println(student.getName()+",叫家長來一下。"); 12 } 13 }
不使用setter方法注入依賴的對象,而是使用構造函數注入依賴的對象。
二、修改Spring容器的配置以下
1 <!-- 初始化BadStudent類的實例lisi--> 2 <bean name="lisi" class="beans.BadStudent"> 3 <constructor-arg value="李四" /> 4 </bean> 5 6 <!--配置依賴--> 7 <bean name="mathTeacher" class="beans.MathTeacher"> 8 <constructor-arg name="student" ref="lisi" /> 9 </bean>
三、運行,看到控制檯打印出「李四,叫家長來一下。」。
value是注入Java的基礎類型,ref是注入依賴的Bean。固然也能夠用<value>、<ref>子元素的形式配置。