一、依賴注入(DI)
依賴注入聽起來很高深的樣子,其實白話就是:給屬性賦值。一共有兩種方法,第一是以構造器參數的形式,另外一種就是以setting方法的形式。
1 構造器注入
1 使用構造器注入
使用xml的注入方式
A. 通過參數的順序
<constructor-arg index="0"><value>張三</value></constructor-arg>
<constructor-arg index="1"><value>56</value></constructor-arg>
B. 通過參數的類型
<constructor-arg type="java.lang.Integer"><value>56</value></constructor-arg>
<constructor-arg type="java.lang.String"><value>張三</value></constructor-arg>
具體實例
假如現在要對一個Person類注入參數,Student是一個另外一個類。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public class Person { private String pid; private String name; private Student student; public Person(String pid, Student student){ this .pid= pid; this .student = student; } public Person(String pid, String name){ this .pid = pid; this .name = name; } } |
配置applicationContext.xml,假如不進行參數配置,則報錯,找不到相應的構造器。配置了相應的參數,則應在類中聲明相應的構造函數。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<? xml version = "1.0" encoding = "UTF-8" ?> < 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 = "person" class = "com.itheima10.spring.di.xml.constructor.Person" > <!-- 不配參數,將會采取默認的構造器 constructor-arg person類中某一個構造器的某一個參數 index 為參數的角標 type 參數的類型 value 如果為基礎屬性,則用這個賦值 ref 引用類型賦值 --> < constructor-arg index = "0" type = "java.lang.String" value = "aaa" ></ constructor-arg > < constructor-arg index = "1" ref = "student" ></ constructor-arg > </ bean > < bean id = "person1" class = "com.itheima10.spring.di.xml.constructor.Person" > < property name = "pid" value = "1" ></ property > </ bean > < bean id = "student" class = "com.itheima10.spring.di.xml.constructor.Student" ></ bean > </ beans > |
編寫測試類DIXMLConstructorTest ,進行斷點調試,將會發現根據配置的參數,進入的構造函數是Person(String pid, Student student)
1
2
3
4
5
6
7
8
|
public class DIXMLConstructorTest { @Test public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml" ); Person person = (Person) context.getBean( "person" ); } } |
2 使用屬性setter方法進行注入
使用xml的注入方式:
A. 簡單Bean的注入
簡單Bean包括兩種類型:包裝類型和String
1
2
3
4
5
|
< bean id = "personService" class = "com.itcast.bean.impl.PersonServiceImpl" > <!-- 基本類型,string類型 --> < property name = "age" value = "20" ></ property > < property name = "name" value = "張無忌" ></ property > </ bean > |
B. 引用其他Bean
1
2
3
4
|
< bean id = "person" class = "com.itcast.bean.Person" /> < bean id = "personService" class = "com.itcast.bean.impl.PersonServiceImpl" > < property name = "person" ref = "person" /> </ bean > |
1.1 裝配list集合
1
2
3
4
5
6
7
|
< property name = "lists" > < list > < value >list1</ value > < value >list2</ value > < ref bean = "person" /> </ list > </ property > |
1.2 裝配set集合
1
2
3
4
5
6
7
|
< property name = "sets" > < set > < value >list1</ value > < value >list2</ value > < ref bean = "person" /> </ set > </ property > |
1.3 裝配map
1
2
3
4
5
6
7
8
9
10
|
< property name = "maps" > < map > < entry key = "01" > < value >map01</ value > </ entry > < entry key = "02" > < value >map02</ value > </ entry > </ map > </ property > |
map中的<entry>的數值和<list>以及<set>的一樣,可以使任何有效的屬性元素,需要注意的是key值必須是String的。
1.4 裝配Properties
1
2
3
4
5
6
|
< property name = "props" > < props > < prop key = "01" >prop1</ prop > < prop key = "02" >prop2</ prop > </ props > </ property > |
具體實例
1.創建兩個對象Person和Student
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package xgp.spring.demo; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; public class Person { private String pid; private String name; private Student student; private List lists; private Set sets; private Map map; private Properties properties; private Object[] objects; public Person(){ System.out.println( "new person" ); } //省略getter和setter方法 } |
1
2
3
4
5
6
7
8
9
10
11
|
package xgp.spring.demo; public class Student { public Student(){ System.out.println( "new student" ); } public void say(){ System.out.println( "student" ); } } |
配置applicationContext.xml文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
<? xml version = "1.0" encoding = "UTF-8" ?> < 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"> <!-- 把person和student放入到spring容器中 property 用來描述Person類的屬性 value 如果是一般屬性,則用value賦值 ref 如果該屬性是引用類型,用ref賦值 --> < bean id = "person" class = "com.itheima10.spring.di.xml.setter.Person" init-method = "init" lazy-init = "true" > < property name = "pid" value = "1" ></ property > < property name = "name" value = "王二麻子" ></ property > < property name = "student" ref = "student" ></ property > < property name = "lists" > < list > < value >list1</ value > < value >list2</ value > < ref bean = "student" /> </ list > </ property > < property name = "sets" > < set > < value >set1</ value > < value >set2</ value > < ref bean = "student" /> </ set > </ property > < property name = "map" > < map > < entry key = "entry1" > < value >map1</ value > </ entry > < entry key = "entry2" > < ref bean = "student" /> </ entry > </ map > </ property > < property name = "properties" > < props > <!-- 不需要引用類型 --> < prop key = "prop1" >prop1</ prop > < prop key = "prop2" >prop2</ prop > </ props > </ property > < property name = "objects" > < list > < value >aa</ value > < value >bb</ value > </ list > </ property > </ bean > < bean id = "student" class = "com.itheima10.spring.di.xml.setter.Student" ></ bean > </ beans > |
編寫測試類DIXMLSetterTest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
package xgp.spring.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import xgp.spring.demo.Person; public class DIXMLSetterTest { /** * spring 容器做的事情: * 1、spring容器做了什么?(1)啟動spring容器 * (2)為person和student兩個bean創建對象 * (3)解析property的name屬性,拼接setter方法,解析property的 * value或者ref屬性,給setter方法傳遞參數,利用反射技術給對象賦值。 * (4)從spring容器中,把對象提取出來,對象調用方法。 * 2、spring容器執行順序是什么? */ @Test public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml" ); Person person = (Person) context.getBean( "person" ); System.out.println(person.getPid()); System.out.println(person.getName()); System.out.println(person.getLists()); System.out.println(person.getSets()); System.out.println(person.getMap()); System.out.println(person.getObjects().length); } } /*1 王五 [list1, list2, xgp.spring.demo.Student@76a9b9c] [set1, set2, xgp.spring.demo.Student@76a9b9c] {entry1=map1, entry2=map2} 2*/ |
spring容器的執行順序
1.都是默認設置
2.設置student(lazy-init=true)
3.設置person(lazy-init=true)
總結
可以采用兩種方法注入參數,構造器要寫對應的構造函數,setter要生成相應的setter方法,并編寫默認的構造器。
2.5 IOC與DI的意義
學了這些,發現有什么意義?下面寫個文檔管理系統例子來說明,需求見下圖
1.編寫Document 接口
1
2
3
4
|
public interface Document { public void read(); public void write(); } |
2、編寫實現類WordDocument ,ExcelDocument ,PDFDocument
1
2
3
4
5
6
7
8
9
|
public class WordDocument implements Document{ public void read() { System.out.println( "word read" ); } public void write() { System.out.println( "word write" ); } } |
3、編寫文檔管理 系統 DocumentManager
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public class DocumentManager { private Document document; public void setDocument(Document document) { this .document = document; } public DocumentManager(){ } public DocumentManager(Document document) { super (); this .document = document; } public void read(){ this .document.read(); } public void write(){ this .document.write(); } } |
4、編寫測試類DocumentTest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
/** * 利用ioc和di能做到完全的面向接口編程 * */ public class DocumentTest { /** * Document document = new WordDocument(); * 這行代碼是不完全的面向接口編程,因為等號的右邊出現了具體的類 */ @Test public void testDocument_NOSPRING(){ Document document = new WordDocument(); DocumentManager documentManager = new DocumentManager(document); documentManager.read(); documentManager.write(); } /** * 在代碼端不知道Document是由誰來實現的,這個是由spring的配置文件決定的 * <bean id="documentManager" class="com.itheima10.spring.iocdi.document.DocumentManager"> <!-- document為一個接口 --> <property name="document"> <!-- wordDocument是一個實現類,賦值給了document接口 --> <ref bean="pdfDocument"/> </property> </bean> */ @Test public void testDocument_Spring(){ ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml" ); DocumentManager documentManager =(DocumentManager)context.getBean( "documentManager" ); documentManager.read(); documentManager.write(); } } |
從上面可以看出不適用spring和適用spring的區別
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<!-- documentManager,wordDocument,excelDocument,pdfDocument放入到spring容器中 --> < bean id = "wordDocument" class = "com.itheima10.spring.iocdi.document.WordDocument" ></ bean > < bean id = "excelDocument" class = "com.itheima10.spring.iocdi.document.ExcelDocument" ></ bean > < bean id = "pdfDocument" class = "com.itheima10.spring.iocdi.document.PDFDocument" ></ bean > < bean id = "documentManager" class = "com.itheima10.spring.iocdi.document.DocumentManager" > <!-- document為一個接口 --> < property name = "document" > <!-- wordDocument是一個實現類,賦值給了document接口 --> < ref bean = "pdfDocument" /> </ property > </ bean > |
使用spring只需要在applicationContext中配置相應的<ref bean="">對象,而不需要關注具體的實現類,實現完全的面向接口編程,這也是為什么spring能夠和這么多工具集成的原因。
2.6 mvc實例–模擬structs2
需求描述
建立工程目錄
編碼:
1、創建Dao層
建立PersonDao接口和實現類PersonDaoImpl
1
2
3
4
5
6
7
8
9
10
|
public interface PersonDao { public void savePerson(); } public class PersonDaoImpl implements PersonDao { @Override public void savePerson() { System.out.println( " save person" ); } } |
2、建立service層,PersonService接口與PersonServiceImpl實現類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public interface PersonService { public void savePerson(); } public class PersonServiceImpl implements PersonService{ private PersonDao personDao; public void setPersonDao(PersonDao personDao) { this .personDao = personDao; } @Override public void savePerson() { this .personDao.savePerson(); } } |
3、建立Action,PersonAction類
1
2
3
4
5
6
7
8
9
10
11
|
public class PersonAction { private PersonService personService; public void setPersonService(PersonService personService) { this .personService = personService; } public void savePerson(){ this .personService.savePerson(); } } |
4、配置applicationContext.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<!-- 把service,dao,action層的類放入到spring容器中 --> < bean id = "personDao" class = "xgp.spring.demo.PersonDaoImpl" ></ bean > < bean id = "personService" class = "xgp.spring.demo.PersonServiceImpl" > < property name = "personDao" > < ref bean = "personDao" /> </ property > </ bean > < bean id = "personAction" class = "xgp.spring.demo.PersonAction" > < property name = "personService" > < ref bean = "personService" /> </ property > </ bean > |
5、編寫測試類testMVC
1
2
3
4
5
6
7
8
9
|
public class MVCTest { @Test public void testMVC(){ ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml" ); PersonAction personAction = (PersonAction)context.getBean( "personAction" ); personAction.savePerson(); //save person } } |
上述實例很清楚的展現出了spring的面向接口編程,service層只需調用dao層的接口,而不需要關注于dao層的實現類,action也只需調用service的接口,而不需要關注service的實現類。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://blog.csdn.net/i10630226/article/details/50507100