前言:在Spring框架中,DI(依賴注入)是用來定義對象彼此間的依賴,主要有set方法注入和構造器注入兩種方式。另外,當一個類包含多個構造函數帶的參數相同,它老是會形成構造函數注入參數類型歧義的問題,我會在第3點進行介紹並給出解決方案。java
1.setter方法注入:spring
package com.yiibai.output; import com.yiibai.output.IOutputGenerator; public class OutputHelper { IOutputGenerator outputGenerator; public void setOutputGenerator(IOutputGenerator outputGenerator){ this.outputGenerator = outputGenerator; } }
一個 bean 配置文件用來聲明bean 和經過 setter 設置注入(property標籤)的依賴。框架
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="OutputHelper" class="com.yiibai.output.OutputHelper"> <property name="outputGenerator"> <ref bean="CsvOutputGenerator" /> </property> </bean> <bean id="CsvOutputGenerator" class="com.yiibai.output.impl.CsvOutputGenerator" /> </beans>
2.構造器注入:yii
例子:函數
package com.yiibai.output; import com.yiibai.output.IOutputGenerator; public class OutputHelper { IOutputGenerator outputGenerator; OutputHelper(IOutputGenerator outputGenerator){ this.outputGenerator = outputGenerator; } }
bean 配置文件來聲明bean並經過構造函數(constructor-arg標籤)設置注入依賴ui
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="OutputHelper" class="com.yiibai.output.OutputHelper"> <constructor-arg> <bean class="com.yiibai.output.impl.CsvOutputGenerator" /> </constructor-arg> </bean> <bean id="CsvOutputGenerator" class="com.yiibai.output.impl.CsvOutputGenerator" /> </beans>
3.當一個類包含多個構造函數帶的參數相同,它老是會形成構造函數注入參數類型歧義的問題。this
讓咱們來看看這個客戶 bean 實例。它包含兩個構造方法,均接受3個不一樣的數據類型參數:spa
package com.yiibai.common; public class Customer { private String name; private String address; private int age; public Customer(String name, String address, int age) { this.name = name; this.address = address; this.age = age; } public Customer(String name, int age, String address) { this.name = name; this.age = age; this.address = address; } //getter and setter methods public String toString(){ return " name : " +name + "\n address : " + address + "\n age : " + age; } }
在Spring bean 的配置文件中,咱們傳遞一個「yiibai' 的名字,地址爲'188',以及年齡爲'28'。code
<!--Spring-Customer.xml--> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="CustomerBean" class="com.yiibai.common.Customer"> <constructor-arg> <value>yiibai</value> </constructor-arg> <constructor-arg> <value>188</value> </constructor-arg> <constructor-arg> <value>28</value> </constructor-arg> </bean> </beans>
運行它,你指望的結果是什麼?xml
package com.yiibai.common; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main( String[] args ) { ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"Spring-Customer.xml"}); Customer cust = (Customer)context.getBean("CustomerBean"); System.out.println(cust); } }
輸出結果:
name : yiibai address : 28 age : 188
其結果不是咱們所指望的,第一個構造器不執行,而是第二構造函數運行。在Spring參數類型'188' 可以轉換成int,因此Spring只是轉換它,並採用第二個構造來執行,即便你認爲它應該是一個字符串。
constructor arguments specified but no matching constructor found in bean 'CustomerBean' (hint: specify index and/or type arguments for simple parameters to avoid type ambiguities
爲了解決這個問題,應該爲構造函數指定的確切數據類型,經過像這樣類型的屬性:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="CustomerBean" class="com.yiibai.common.Customer"> <constructor-arg type="java.lang.String"> <value>yiibai</value> </constructor-arg> <constructor-arg type="java.lang.String"> <value>188</value> </constructor-arg> <constructor-arg type="int"> <value>28</value> </constructor-arg> </bean> </beans>
再次運行它,如今獲得你所指望的:
name : yiibai address : 188 age
總結:在依賴注入中,主要有seter方法注入和構造函數注入兩種方式,其中setter方法注入是在xml配置文件中經過property設置依賴,而構造器經過constructor-arg設置依賴;
顯式聲明每一個構造函數參數的數據類型,能夠避免上述構造注入型歧義的問題。