JavaWeb Spring依賴注入深入學(xué)習(xí)
一、依賴注入(DI)
依賴注入聽起來很高深的樣子,其實白話就是:給屬性賦值。一共有兩種方法,第一是以構(gòu)造器參數(shù)的形式,另外一種就是以setting方法的形式。
1 構(gòu)造器注入
1 使用構(gòu)造器注入
使用xml的注入方式
A. 通過參數(shù)的順序
<constructor-arg index="0"><value>張三</value></constructor-arg>
<constructor-arg index="1"><value>56</value></constructor-arg>
B. 通過參數(shù)的類型
<constructor-arg type="java.lang.Integer"><value>56</value></constructor-arg>
<constructor-arg type="java.lang.String"><value>張三</value></constructor-arg>
具體實例
假如現(xiàn)在要對一個Person類注入?yún)?shù),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,假如不進行參數(shù)配置,則報錯,找不到相應(yīng)的構(gòu)造器。配置了相應(yīng)的參數(shù),則應(yīng)在類中聲明相應(yīng)的構(gòu)造函數(shù)。
<?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">
<!--
不配參數(shù),將會采取默認(rèn)的構(gòu)造器
constructor-arg person類中某一個構(gòu)造器的某一個參數(shù)
index 為參數(shù)的角標(biāo)
type 參數(shù)的類型
value 如果為基礎(chǔ)屬性,則用這個賦值
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 ,進行斷點調(diào)試,將會發(fā)現(xiàn)根據(jù)配置的參數(shù),進入的構(gòu)造函數(shù)是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" class="com.itcast.bean.impl.PersonServiceImpl"> <!-- 基本類型,string類型 --> <property name="age" value="20"></property> <property name="name" value="張無忌"></property> </bean>
B. 引用其他Bean
<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集合
<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>的數(shù)值和<list>以及<set>的一樣,可以使任何有效的屬性元素,需要注意的是key值必須是String的。
1.4 裝配Properties
<property name="props"> <props> <prop key="01">prop1</prop> <prop key="02">prop2</prop> </props> </property>
具體實例
1.創(chuàng)建兩個對象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" 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
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創(chuàng)建對象
* (3)解析property的name屬性,拼接setter方法,解析property的
* value或者ref屬性,給setter方法傳遞參數(shù),利用反射技術(shù)給對象賦值。
* (4)從spring容器中,把對象提取出來,對象調(diào)用方法。
* 2、spring容器執(zhí)行順序是什么?
*/
@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容器的執(zhí)行順序
1.都是默認(rèn)設(shè)置

2.設(shè)置student(lazy-init=true)

3.設(shè)置person(lazy-init=true)

總結(jié)
可以采用兩種方法注入?yún)?shù),構(gòu)造器要寫對應(yīng)的構(gòu)造函數(shù),setter要生成相應(yīng)的setter方法,并編寫默認(rèn)的構(gòu)造器。
2.5 IOC與DI的意義
學(xué)了這些,發(fā)現(xiàn)有什么意義?下面寫個文檔管理系統(tǒng)例子來說明,需求見下圖
1.編寫Document 接口
public interface Document {
public void read();
public void write();
}
2、編寫實現(xiàn)類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、編寫文檔管理 系統(tǒng) 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();
* 這行代碼是不完全的面向接口編程,因為等號的右邊出現(xiàn)了具體的類
*/
@Test
public void testDocument_NOSPRING(){
Document document = new WordDocument();
DocumentManager documentManager = new DocumentManager(document);
documentManager.read();
documentManager.write();
}
/**
* 在代碼端不知道Document是由誰來實現(xiàn)的,這個是由spring的配置文件決定的
* <bean id="documentManager"
class="com.itheima10.spring.iocdi.document.DocumentManager">
<!--
document為一個接口
-->
<property name="document">
<!--
wordDocument是一個實現(xiàn)類,賦值給了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的區(qū)別
<!--
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是一個實現(xiàn)類,賦值給了document接口
-->
<ref bean="pdfDocument"/>
</property>
</bean>
使用spring只需要在applicationContext中配置相應(yīng)的<ref bean="">對象,而不需要關(guān)注具體的實現(xiàn)類,實現(xiàn)完全的面向接口編程,這也是為什么spring能夠和這么多工具集成的原因。
2.6 mvc實例–模擬structs2
需求描述

建立工程目錄

編碼:
1、創(chuàng)建Dao層
建立PersonDao接口和實現(xiàn)類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實現(xiàn)類
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" 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
public class MVCTest {
@Test
public void testMVC(){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
PersonAction personAction = (PersonAction)context.getBean("personAction");
personAction.savePerson();//save person
}
}
上述實例很清楚的展現(xiàn)出了spring的面向接口編程,service層只需調(diào)用dao層的接口,而不需要關(guān)注于dao層的實現(xiàn)類,action也只需調(diào)用service的接口,而不需要關(guān)注service的實現(xiàn)類。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java中有界隊列的飽和策略(reject policy)原理解析
這篇文章主要介紹了Java中有界隊列的飽和策略(reject policy)原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-04-04
在Java中Collection的一些常用方法總結(jié)
今天給大家?guī)淼闹R是關(guān)于Java的,文章圍繞著Java中Collection的一些常用方法展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06
如何基于java向mysql數(shù)據(jù)庫中存取圖片
這篇文章主要介紹了如何基于java向mysql數(shù)據(jù)庫中存取圖片,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-02-02
詳解JAVA高質(zhì)量代碼之?dāng)?shù)組與集合
在學(xué)習(xí)編程的過程中,我覺得不止要獲得課本的知識,更多的是通過學(xué)習(xí)技術(shù)知識提高解決問題的能力,這樣我們才能走在最前方,本文主要講述Java高質(zhì)量代碼之?dāng)?shù)組與集合2013-08-08
基于ElasticSearch Analyzer的使用規(guī)則詳解
這篇文章主要介紹了基于ElasticSearch Analyzer的使用規(guī)則,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07

