springMVC 學習(什么是依賴注入)
來源:程序員人生 發布時間:2015-05-05 07:43:52 閱讀次數:3695次
上1篇博文中,我們學習了springIOC,又稱spring控制反轉,行將對象的創建燒毀等操作交給spring容器來處理,今天學習spring的依賴注入,那末甚么是依賴注入,說的通俗1點,就是對屬性賦值,也就是說我們利用spring來為我們的類中包括的屬性來進行賦值,想一想之前我們是通過這樣的方式來編寫代碼的:接口
對象 = new 接口實現類(); 再看看我們之前是怎樣給屬性賦值的
1.通過set方法
2.通過構造方法
今天我們來實現通過spring依賴注入來為類中的變量賦值。首先我新建1個Student.java和1個Teacher.java類,并且提供get和set方法
package com.test.di;
public class Student {
private String name;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
package com.test.di;
public class Teacher {
private String teacherName;
private Student student;
public String getTeacherName() {
return teacherName;
}
public void setTeacherName(String teacherName) {
this.teacherName = teacherName;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
}
然后,我們在spring配置文件中來為這些屬性賦值:
<?xml version="1.0" encoding="UTF⑻"?>
<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⑵.5.xsd">
<bean id="student" class="com.test.di.Student">
<property name="name" value="haha"></property>
<property name="id" value="12"></property>
</bean>
<bean id="teacher" class="com.test.di.Teacher">
<property name="teacherName" value="teacherWang"></property>
<property name="student" ref="student"></property>
</bean>
</beans>
根據配置文件,我們可以發現,在bean中有個property的配置,其中name就是我要為那個屬性賦值,對屬性的值,這里有兩種情況:
1.如果是基本類型,直接在value中寫上需要賦的值便可
2.如果是援用類型,那末需要使用ref來援用對應的類,對這個栗子,即student這里ref所援用的student就是第1個student的bean中配置的id。
接下來,我編寫1個測試類,來測試是不是成功的為屬性注入對應的值DiTest.java
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/test/di/applicationContext.xml");
Teacher teacher = (Teacher) applicationContext.getBean("teacher");
Student student = teacher.getStudent();
System.out.println(teacher.getTeacherName());
System.out.println("studentName :"+student.getName()+"==studentId :"+student.getId());
此時打印結果以下:
teacherWang
studentName :haha==studentId :12
發現這個時候spring容器已為我們的屬性賦值成功了。但是我們卻并沒有像之前那樣調用set方法,或是構造方法,這里有1點需要說明,就是我們雖然沒有自己調用set方法來為屬性賦值,但是spring還是會掉用set方法,所以我們如果想對某1個屬性進行依賴注入的話,那末我們就需要對該屬性寫上set方法。
下面我們為teacher注入1些集合,首先需要做的就是在Teacher.java中聲明list,set,map這3個屬性,然后為這些屬性生成set方法,新增屬性以下:
private List<String>lists;
private Set<Integer>sets;
private Map<Integer,String>maps;
然后再spring的配置文件中這樣為其賦值:
<bean id="teacher" class="com.test.di.Teacher">
<property name="teacherName" value="teacherWang"></property>
<property name="student" ref="student"></property>
<property name="lists">
<list>
<value>one</value>
<value>two</value>
<value>three</value>
</list>
</property>
<property name="maps">
<map>
<entry key="1" value="firstMap"></entry>
<entry key="2" value="secondMap"></entry>
<entry key="3" value="thirdMap"></entry>
</map>
</property>
<property name="sets">
<set>
<value>111</value>
<value>222</value>
<value>333</value>
</set>
</property>
</bean>
可以發現這個配置文件寫起來和普通的集合對象的情勢是很相似的,這里我們都是用的基本的類型來作為集合的泛型,如果使用的是援用類型,這里的配置都有ref對應的屬性,只需要將所需要援用的類對象的id寫入到ref的值當中便可,舉個栗子:
對list和set如果泛型是援用類型,那末可以這樣寫:
<ref bean=""/>
而對map如果類型是援用類型,可以這樣寫:
<entry key-ref="" value-ref=""></entry>
好了,是時候驗證是不是賦值成功了。IocTest.java
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/test/di/applicationContext.xml");
Teacher teacher = (Teacher) applicationContext.getBean("teacher");
Student student = teacher.getStudent();
System.out.println(teacher.getTeacherName());
System.out.println("studentName :"+student.getName()+"==studentId :"+student.getId());
List<String> lists = teacher.getLists();
for (String string : lists) {
System.out.println(string);
}
Map<Integer,String>maps = teacher.getMaps();
for(Entry<Integer,String>entry :maps.entrySet()) {
System.out.println(maps.get(entry.getKey()));
}
Set<Integer>sets = teacher.getSets();
for (Integer integer : sets) {
System.out.println(integer);
}
此時打印的結果以下:
teacherWang
studentName :haha==studentId :12
one
two
three
firstMap
secondMap
thirdMap
111
222
333
可以發現這個時候spring成功為所有的寫了set方法的屬性成功賦值了。好了上邊的都是利用set方法來為屬性賦值的,下面我們來利用構造方法來為屬性賦值,我們寫1個ClassInfo.java類:
package com.test.di;
public class ClassInfo {
private String className;
private Student student;
public ClassInfo(String className, Student student) {
super();
this.className = className;
this.student = student;
}
public String getClassName() {
return className;
}
public Student getStudent() {
return student;
}
}
可以看到此時我們聲明了兩個屬性,1個基本類型的,1個援用類型的,并且書寫了構造方法,這時候我們就能夠在spring配置文件中,利用構造方法來為屬性賦值了,在bean的配置中有這樣1個配置
<constructor-arg index="" type="" ref="" value=""></constructor-arg>
顧名思義就是根據構造函數來為屬性賦值的,說明1下這4個參數的意思:
index:該參數在構造方法中的位置,默許從0開始
type:該參數的類型
ref: 如果該參數是援用類型時候的援用id
value:如果該參數是基本類型時候的值
知道了每一個參數的意思,寫起來就很簡單了,我的ClassInfo.java對應的bean以下:
<bean id="classInfo" class="com.test.di.ClassInfo">
<constructor-arg index="0" type="java.lang.String" value="testConstructor"></constructor-arg>
<constructor-arg index="1" type="com.test.di.Student" ref="student"></constructor-arg>
</bean>
編寫測試代碼:
ClassInfo classInfo = (ClassInfo) applicationContext.getBean("classInfo");
System.out.println("classInfo.getClassName():"+classInfo.getClassName());
System.out.println("studentId:"+classInfo.getStudent().getId()+"==studentName"+classInfo.getStudent().getName());
此時會正確的答應出我們設置的信息,以下:
classInfo.getClassName():testConstructor
studentId:12==studentNamehaha
現在我們已學會了如何在spring中為屬性賦值,如之前所屬,我們并沒有調用set或構造方法,卻能成功為屬性賦值,其實我們是把set方法的調用交給spring來處理了,那末依賴注入又有甚么用呢?我們為何要學習依賴注入?還記得我在該篇最開始寫了這樣1句話:接口 對象 = new 接口實現類(); 這類方式是我們之前創建對象的方法?,F在我舉個栗子:
我新建1個借口BookRead然后建倆個類實現該接口:
package com.test.why.di;
public interface BookRead {
public void readBook();
}
package com.test.why.di;
public class KindleRead implements BookRead {
@Override
public void readBook() {
System.out.println("use kindle read");
}
}
package com.test.why.di;
public class PhoneRead implements BookRead {
@Override
public void readBook() {
System.out.println("use phone read");
}
}
package com.test.why.di;
public class ReadBy {
private BookRead bookRead;
public ReadBy(BookRead bookRead) {
this.bookRead = bookRead;
}
public void read() {
bookRead.readBook();
}
}
如果我現在需要先用kindle來讀書怎樣辦呢?依照之前的寫法:
BookRead bookRead = new KindleRead();
ReadBy readBy = new ReadBy(bookRead);
readBy.read();
那末問題來了,如果我現在需要利用Phone來讀書,那末我是否是需要重新new1個PhoneRead呢。這樣做其實不是我們要的面向接口編程。接下來我們使用spring的依賴注入來為其優化:
首先將兩種讀書方式的類,在spring容器中進行配置:
<bean id="kindleRead" class="com.test.why.di.KindleRead">
</bean>
<bean id="phoneRead" class="com.test.why.di.PhoneRead">
</bean>
然后配置ReadBy對應的bean:
<bean id="readBy" class="com.test.why.di.ReadBy">
<property name="bookRead" ref="kindleRead"></property>
</bean>
測試:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/test/di/applicationContext.xml");
ReadBy readBy = (ReadBy) applicationContext.getBean("readBy");
readBy.read();
這里我為readBy注入的是kindleRead,因此這時候候我調用readBy.read();方法應當是運行的kindleRead的readBook,其實這里已做到了面向接口編程,就是我的readBy.read();不需要知道bookRead是甚么類型,我只需要調用在read方法中調用bookRead.readBook();方法就能夠了,具體以哪一種方式來讀書,我只需要在spring容器當中進行配置便可,這樣做也使得代碼更加容易保護。
好了,今天的springDi就學習到這里了。
源碼下載
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈