一、依賴注入(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是一個另外一個類。
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,假如不進行參數配置,則報錯,找不到相應的構造器。配置了相應的參數,則應在類中聲明相應的構造函數。
<?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"> <!-- 不配參數,將會採取默認的構造器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"> <property name="pid" value="1"></property> </bean> <bean id="student"></bean></beans>
編寫測試類DIXMLConstructorTest ,進行斷點調試,將會發現根據配置的參數,進入的構造函數是Person(String pid, Student student)
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
<bean id="personService"><!-- 基本類型,string類型--><property name="age" value="20"></property><property name="name" value="張無忌"></property> </bean>
B. 引用其他Bean
<bean id="person" /> <bean id="personService"> <property name="person" ref="person" /></bean>
1.1 裝配list集合
<property name="lists"> <list> <value>list1</value> <value>list2</value> <ref bean="person" /> </list></property>
1.2 裝配set集合
<property name="sets"> <set> <value>list1</value> <value>list2</value> <ref bean="person" /> </set></property>
1.3 裝配map
<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
<property name="props"> <props> <prop key="01">prop1</prop> <prop key="02">prop2</prop> </props></property>
具體實例
1.創建兩個對象Person和Student
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方法} package xgp.spring.demo;public class Student { public Student(){ System.out.println("new student"); } public void say(){ System.out.println("student"); }}配置applicationContext.xml文件
<?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" 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"></bean></beans>
編寫測試類DIXMLSetterTest
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 接口
public interface Document { public void read(); public void write();}2、編寫實現類WordDocument ,ExcelDocument ,PDFDocument
public class WordDocument implements Document{ public void read() { System.out.println("word read"); } public void write() { System.out.println("word write"); }}3、編寫文檔管理系統DocumentManager
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
/** * 利用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" > <!-- 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的區別
<!-- documentManager,wordDocument,excelDocument,pdfDocument放入到spring容器中--> <bean id="wordDocument"></bean> <bean id="excelDocument"></bean> <bean id="pdfDocument"></bean> <bean id="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
public interface PersonDao { public void savePerson();}public class PersonDaoImpl implements PersonDao { @Override public void savePerson() { System.out.println(" save person"); }}2、建立service層,PersonService接口與PersonServiceImpl實現類
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類
public class PersonAction { private PersonService personService; public void setPersonService(PersonService personService) { this.personService = personService; } public void savePerson(){ this.personService.savePerson(); }}4、配置applicationContext.xml
<!-- 把service,dao,action層的類放入到spring容器中--> <bean id="personDao"></bean> <bean id="personService"> <property name="personDao"> <ref bean="personDao"/> </property> </bean> <bean id="personAction"> <property name="personService"> <ref bean="personService"/> </property> </bean>
5、編寫測試類testMVC
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的實現類。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。