JavaWeb及其框架技術(shù) 課件 陳振興 第8-11章 Spring框架基礎(chǔ)- SSM整合應(yīng)用案例_第1頁
JavaWeb及其框架技術(shù) 課件 陳振興 第8-11章 Spring框架基礎(chǔ)- SSM整合應(yīng)用案例_第2頁
JavaWeb及其框架技術(shù) 課件 陳振興 第8-11章 Spring框架基礎(chǔ)- SSM整合應(yīng)用案例_第3頁
JavaWeb及其框架技術(shù) 課件 陳振興 第8-11章 Spring框架基礎(chǔ)- SSM整合應(yīng)用案例_第4頁
JavaWeb及其框架技術(shù) 課件 陳振興 第8-11章 Spring框架基礎(chǔ)- SSM整合應(yīng)用案例_第5頁
已閱讀5頁,還剩212頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第8章Spring框架基礎(chǔ)掌握Spring框架的相關(guān)配置掌握Spring框架依賴注入的3種方式掌握Spring框架Bean的作用域和裝配方式掌握Spring框架中的組件掃描及注解開發(fā)掌握Spring框架中AOP的開發(fā)學(xué)習(xí)目標(biāo)8.1.1Spring框架的基本概念Spring框架是一個(gè)基于Java平臺的輕量級、一站式構(gòu)建企業(yè)級應(yīng)用的解決方案,提供全面的基礎(chǔ)架構(gòu)支持開發(fā)Java應(yīng)用程序。Spring框架提供了聲明式事務(wù)管理、遠(yuǎn)程訪問、Web服務(wù),以及數(shù)據(jù)持久化等方面的技術(shù)支持。Spring框架的用途不僅局限于服務(wù)端的開發(fā),任何Java應(yīng)用都可以從中受益。Spring框架采用分層架構(gòu),根據(jù)不同的功能被劃分成多個(gè)模塊,這些模塊大體可分為數(shù)據(jù)訪問/集成層、Web層、AOP層、核心容器層和測試層5個(gè)模塊(見圖8-1)。Spring框架允許自由選擇需要使用的模塊,不必引入其余模塊。8.1Spring框架的簡介測試層:Test模塊使用Junit框架或TestNG框架進(jìn)行測試,提供對Spring應(yīng)用的單元測試和集成測試支持。8.1Spring框架的簡介圖8-1Spring框架整體結(jié)構(gòu)核心容器層(CoreContainer):Spring框架的核心容器是其他模塊建立的基礎(chǔ)部分,由Beans、Core、Context和ExpressionLanguage(SpEL)模塊組成。Beans模塊提供了BeanFactory接口,是工廠模式的經(jīng)典實(shí)現(xiàn),在Spring框架中,管理對象通常被稱為Bean實(shí)例。Core核心模塊提供了Spring框架的基本組成部分,包括控制反轉(zhuǎn)(IoC)和依賴注入(DI)功能。Context上下文模塊建立在Core模塊和Beans模塊的基礎(chǔ)之上,是訪問定義和配置任何對象的媒介。ExpressionLanguage模塊是運(yùn)行時(shí)查詢和操作對象圖的強(qiáng)大的表達(dá)式語言。AOP層:包括AOP、Aspects、Instrumentation、Messaging模塊。AOP模塊提供了面向切面的編程實(shí)現(xiàn),允許定義方法攔截器和切入點(diǎn),將代碼按照功能進(jìn)行分離,以降低模塊之間的耦合性。Aspects模塊提供了一個(gè)功能強(qiáng)大且成熟的面向切面編程的AspectJ框架的集成。Instrumentation模塊提供了類工具的支持和類加載器的實(shí)現(xiàn)。Messaging模塊提供了對消息傳遞體系的支持。8.1Spring框架的簡介數(shù)據(jù)訪問/集成層(DataAccess/Integration):包括JDBC、ORM、OXM、JMS和Transactions模塊。JDBC模塊提供了一個(gè)JDBC的抽象層,大幅減少了在開發(fā)過程中對數(shù)據(jù)庫操作的編碼。ORM模塊為JPA、JDO、Hibernate和iBatis等數(shù)據(jù)庫框架提供了集成方案,還提供了一個(gè)支持實(shí)體對象/XML映射的抽象層實(shí)現(xiàn)方案,如JAXB、Castor、XMLBeans、JiBX和XStream。JMS模塊指的是Java消息服務(wù),具有生產(chǎn)和消費(fèi)信息的功能。Transactions模塊是事務(wù)模塊,支持編程和聲明式事務(wù)管理。Web層:包括Web、Servlet、WebSocket和Portlet模塊。Web模塊提供了Web開發(fā)所需的必要組件,如多文件上傳功能,可以使用Servlet監(jiān)聽器來初始化SpringIoC容器及Web應(yīng)用上下文。Servlet模塊提供了MVC模式的Web應(yīng)用程序?qū)崿F(xiàn)方法。Portlet模塊提供了在Portlet環(huán)境中與Web服務(wù)相關(guān)的支持。8.1Spring框架的簡介8.1.2在IDEA中配置Spring應(yīng)用程序1.創(chuàng)建項(xiàng)目(1)首先打開IDEA,點(diǎn)擊NewProject→Java,配置好Java的SDK后,單擊“NEXT”按鈕,得到如圖8-2所示的窗口。圖8-2IDEA中新建Java項(xiàng)目8.1Spring框架的簡介(2)其次彈出是否創(chuàng)建模板選項(xiàng),如圖8-3所示,直接單擊“Next”按鈕跳過即可。(3)最后輸入項(xiàng)目名稱(Projectname),單擊“Finish”按鈕,如圖8-4所示,此時(shí)完成項(xiàng)目的創(chuàng)建操作。8.1Spring框架的簡介圖8-3創(chuàng)建模板選項(xiàng)窗口圖8-4項(xiàng)目名稱修改窗口2.添加Spring框架支持共有兩種添加Spring框架支持的方法。(1)方式一。①在IDEA中右擊項(xiàng)目文件夾,單擊“AddFrameworkSupport...”(見圖8-5)。②在彈出的AddFrameworkSupport窗口左側(cè)勾選Spring框架后,在右側(cè)勾選Createemptyspring-config.xml選項(xiàng)和Download選項(xiàng),如圖8-6所示。8.1Spring框架的簡介圖8-5選擇“AddFrameworkSupport...”8.1Spring框架的簡介③單擊“OK”按鈕后,IDEA會自動下載Spring框架的依賴jar包,并創(chuàng)建一個(gè)空白的spring-config.xml配置文件,到這里Spring框架的開發(fā)環(huán)境已經(jīng)配置完成,目錄結(jié)構(gòu)如圖8-7所示。項(xiàng)目根目錄下生成的lib文件夾就是Spring框架相關(guān)組件的jar包,src目錄的spring-config.xml就是Spring框架的配置文件,后面編寫的Java代碼都放置在src目錄下。圖8-6打開的AddFrameworkSupport窗口圖8-7項(xiàng)目的目錄結(jié)構(gòu)8.1Spring框架的簡介(2)方式二。在方式一中,通過IDEA的AddFrameworkSupport窗口添加框架支持可供選擇的方法版本有限,我們還可以通過另一種方式實(shí)現(xiàn)。①在根目錄中創(chuàng)建一個(gè)libs文件夾,將從官網(wǎng)下載的Spring框架的相關(guān)jar包放入該文件夾下,右擊libs文件夾,單擊“AddasLibrary”,將其添加為項(xiàng)目的lib庫,如圖8-8所示。圖8-8添加依賴庫8.1Spring框架的簡介②鼠標(biāo)右擊src目錄,選擇New→XMLConfigurationFile→SpringConfig,可以創(chuàng)建一個(gè)spring-config.xml配置文件,如圖8-9所示。圖8-9方式二中創(chuàng)建Spring配置文件8.2SpringIoC容器8.2.1SpringIoC容器概述控制反轉(zhuǎn)(InversionofControl,IoC)能夠?qū)?chuàng)建實(shí)例的權(quán)利反轉(zhuǎn)給SpringIoC容器,由SpringIoC容器創(chuàng)建實(shí)例。這是面向?qū)ο缶幊痰囊环N設(shè)計(jì)原則,可以用來降低計(jì)算機(jī)代碼之間的耦合度。在軟件工程中,耦合度指的是對象之間的依賴性,對象之間的耦合度越強(qiáng),維護(hù)成本越高。耦合度的強(qiáng)弱取決于模塊間接口的復(fù)雜性、調(diào)用模塊的方式,以及通過界面?zhèn)魉蛿?shù)據(jù)的多少。當(dāng)某個(gè)Java對象(調(diào)用者)需要調(diào)用另一個(gè)Java對象(被調(diào)用者,即被依賴對象)時(shí),在傳統(tǒng)程序中,調(diào)用者通常會采用new運(yùn)算符創(chuàng)建一個(gè)對象,這種方式會導(dǎo)致調(diào)用者與被調(diào)用者之間的耦合度增強(qiáng),不利于后期項(xiàng)目的升級和維護(hù)。調(diào)用者創(chuàng)建被調(diào)用者如圖8-10所示。8.2SpringIoC容器圖8-10調(diào)用者創(chuàng)建被調(diào)用者在使用Spring框架后,對象的實(shí)例不再由調(diào)用者創(chuàng)建,而是由SpringIoC容器創(chuàng)建,對象之間的關(guān)系由SpringIoC容器負(fù)責(zé)控制,不再由調(diào)用者控制。這樣,對象之間的這種依賴關(guān)系由程序轉(zhuǎn)移到SpringIoC容器,控制權(quán)發(fā)生了反轉(zhuǎn),這就是Spring框架的控制反轉(zhuǎn)。從SpringIoC容器的角度看,SpringIoC容器負(fù)責(zé)將被依賴對象賦值給調(diào)用者的成員變量,這相當(dāng)于調(diào)用者注入了它依賴的實(shí)例,這就是Spring框架的依賴注入,如圖8-11所示。8.2SpringIoC容器圖8-11由容器注入被調(diào)用者控制反轉(zhuǎn)也被稱為依賴注入(DependencyInjection,DI),是面向?qū)ο缶幊痰囊环N設(shè)計(jì)理念,用來降低程序代碼間的耦合度,在MVC的設(shè)計(jì)模式中經(jīng)常使用。我們首先需要考慮什么是依賴。依賴在代碼中一般指通過局部變量、方法參數(shù)、返回值等建立的對于其他對象的調(diào)用關(guān)系。例如,在A類的方法中,實(shí)例化了B類的對象并調(diào)用其方法以完成特定的功能,即A類依賴B類。SpringIoC容器實(shí)現(xiàn)了控制反轉(zhuǎn)和依賴注入,使用某種形式的配置文件(可以用XML、Java注解或Java代碼方式來編寫)告訴SpringIoC容器要實(shí)例化、配置和組裝應(yīng)用程序中的哪些對象,這些對象在SpringIoC容器中被稱為Bean。8.2SpringIoC容器在Spring框架中,BeanFactory接口和ApplicationContext接口都可以代表SpringIoC容器。其中最基本的接口就是BeanFactory接口,負(fù)責(zé)配置、創(chuàng)建、管理Bean。ApplicationContext接口是BeanFactory接口的子接口,也被稱為Spring上下文。另外,ApplicationContext接口還是ResourceLoader接口的子接口,擁有加載配置文件的一些方法。ApplicationContext接口有以下實(shí)現(xiàn)類。(1)ClassPathXmlApplicationContext實(shí)現(xiàn)類從類路徑下加載XML配置文件來初始化容器。(2)FileSystemXmlApplicationContext實(shí)現(xiàn)類從系統(tǒng)文件目錄中加載XML配置文件來初始化容器。(3)AnnotationConfigApplicationContext實(shí)現(xiàn)類通過解析注解的方式來初始化容器。8.2SpringIoC容器例8-1SpringIoC容器的基本使用步驟。(1)編寫B(tài)ean類的對象代碼。在src目錄下創(chuàng)建一個(gè)org.example.dao包來放置持久層類代碼,在該包中創(chuàng)建一個(gè)UserDao類,添加一個(gè)getUserList()方法,代碼如下。packageorg.example.dao;

//UserDao類

publicclassUserDao{

//獲取用戶列表方法

publicvoidgetUserList(){

//用輸入語句來代替功能的執(zhí)行

System.out.println("獲取用戶列表...");

}

}8.2SpringIoC容器(2)編寫配置文件,裝配bean。在Spring-config.xml配置文件中使用bean標(biāo)簽,以及bean標(biāo)簽的id屬性給這個(gè)bean起別名,并使用class屬性配置這個(gè)bean的全限定類名(包名.類名),代碼如下。<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="/schema/beans"

xmlns:xsi="/2001/XMLSchema-instance"

xsi:schemaLocation="/schema/beans

/schema/beans/spring-beans.xsd">

<!--裝配bean-->

<beanid="userDao"class="org.example.dao.UserDao"></bean>

</beans>編寫上述配置文件后,Spring框架會根據(jù)bean標(biāo)簽中class屬性的全限定類名找到org.example.dao包下的UserDao類,并新建(new)一個(gè)userDao對象,將其裝配到SpringIoC容器中;使用id屬性起的別名是這個(gè)bean在容器中的名稱,后續(xù)從容器中獲取bean時(shí)可以使用這個(gè)id名來獲取。若沒有定義id名,則SpringIoC容器在默認(rèn)裝配bean時(shí)用類名的首字母小寫形式作為別名。8.2SpringIoC容器(3)創(chuàng)建SpringIoC容器對象,獲取bean。①創(chuàng)建SpringIoC容器對象。首先創(chuàng)建一個(gè)org.example.test包來放置測試代碼,在這個(gè)包中新建一個(gè)Test01測試類,在main()方法中使用ClassPathXmlApplicationContext類創(chuàng)建SpringIoC容器,傳入配置文件名稱,即“spring-config.xml”,由此便可通過讀取類目錄下的配置文件來初始化SpringIoC容器。②獲取bean對象??梢酝ㄟ^SpringIoC容器的getBean()方法從容器中獲取bean。傳入的參數(shù)可以是字符串形式(配置文件中bean標(biāo)簽的id名),通過這種方式獲取的對象是Object類型的對象,需要進(jìn)行強(qiáng)制類型轉(zhuǎn)換(向下轉(zhuǎn)型);傳入的參數(shù)也可以是類的字節(jié)碼形式,通過這種方式獲取的對象就是傳入?yún)?shù)中指定類型的對象。Spring框架自動對這個(gè)對象進(jìn)行了類型轉(zhuǎn)換。8.2SpringIoC容器③執(zhí)行Bean中的方法。通過獲取的bean可以直接執(zhí)行bean中的方法,代碼如下。packageorg.example.test;

publicclassTest1{

publicstaticvoidmain(String[]args){

//創(chuàng)建SpringIoC容器:讀取類目錄下的配置文件

ApplicationContextcontext=newClassPathXmlApplicationContext("spring-config.xml");

//從SpringIoC容器中獲取bean:通過配置文件bean標(biāo)簽的id名來獲取對象,須進(jìn)行強(qiáng)制類型轉(zhuǎn)換

UserDaouserDao1=(UserDao)context.getBean("userDao");

userDao1.getUserList();

//從SpringIoC容器中獲取bean:通過類的字節(jié)碼來獲取對象,無須進(jìn)行強(qiáng)制類型轉(zhuǎn)換

UserDaouserDao2=context.getBean(UserDao.class);

userDao2.getUserList();

}

}8.2SpringIoC容器getUserList()方法正常執(zhí)行,執(zhí)行結(jié)果如圖8-12所示,說明通過配置文件bean標(biāo)簽的id名和類的字節(jié)碼來獲取對象的兩種形式均可以獲取bean,并執(zhí)行bean中的方法。圖8-12getUserList()方法正常執(zhí)行的結(jié)果8.2SpringIoC容器例8-1通過ClassPathXmlApplicationContext實(shí)現(xiàn)類從類路徑下加載XML配置文件來初始化容器;Spring框架還支持從系統(tǒng)文件目錄中加載XML配置文件來初始化容器,需要使用FileSystemXmlApplicationContext實(shí)現(xiàn)類,代碼形式如下。//創(chuàng)建SpringIoC容器:讀取文件系統(tǒng)下的配置文件

ApplicationContextcontext=newFileSystemXmlApplicationContext("C:\\Users\\Jian\\IdeaProjects\\CH8\\CH8_EX1\\src\\spring-config.xml");基于Java配置類,AnnotationConfigApplicationContext實(shí)現(xiàn)類可通過解析注解的方式初始化SpringIoC容器,此時(shí)傳入的參數(shù)是配置類的字節(jié)碼文件,代碼形式如下。//創(chuàng)建SpringIoC容器:讀取Java配置類中的配置

ApplicationContextcontext=newAnnotationConfigApplicationContext(SpringConfig.class);由于這些實(shí)現(xiàn)類都是ApplicationContext類的子類,所以從容器中獲取Bean都是通過getBean()方法實(shí)現(xiàn)的。8.2SpringIoC容器8.2.2SpringIoC容器的設(shè)計(jì)在Spring框架中,bean是一個(gè)廣義的概念,任何的Java對象、Java組件(包括數(shù)據(jù)源、事務(wù)管理器等)都被當(dāng)成bean來處理。SpringIoC容器除負(fù)責(zé)創(chuàng)建bean外,還要管理bean之間的依賴關(guān)系。SpringIoC容器的設(shè)計(jì)思想是應(yīng)用程序類與配置文件相結(jié)合,如圖8-13所示。配置文件中記錄了Spring框架要?jiǎng)?chuàng)建的bean及bean之間的依賴關(guān)系等內(nèi)容,由SpringIoC容器創(chuàng)建并管理對象。當(dāng)要使用這些bean時(shí),可以直接從SpringIoC容器提供的方法中獲取。圖8-13SpringIoC容器的設(shè)計(jì)思想8.2SpringIoC容器狹義上的SpringIoC容器,在底層源碼上就是一個(gè)Map集合。這個(gè)Map集合存儲的鍵(key)是當(dāng)前bean的別名,若不指定,則默認(rèn)將class類名的首字母小寫作為key,bean信息作為值(value)。存儲bean的Map集合在DefaultListableBeanFactory類中。DefaultListableBeanFactory類的部分源碼如下。/**Mapofbeandefinitionobjects,keyedbybeanname.*/privatefinalMap<String,BeanDefinition>beanDefinitionMap=newConcurrentHashMap<>(256);當(dāng)SpringIoC容器掃描到Bean時(shí),會將這個(gè)bean的描述信息以包名加類名的方式存到beanDefinitionMap中,而value是bean的定義對象beanDefinition,存儲的是類的定義(描述信息)。8.2SpringIoC容器SpringIoC容器在啟動的過程中,對bean進(jìn)行初始化、實(shí)例化時(shí),大致分為兩步:第一步將class文件轉(zhuǎn)換為beanDefinition對象,第二步根據(jù)beanDefinition對象,按照配置的要求進(jìn)行初始化、實(shí)例化。SpringIoC容器為什么不在掃描到class文件后,立即進(jìn)行初始化、實(shí)例化呢?這是因?yàn)樵赟pring框架提供的容器管理功能中,某些class類并不需要立刻初始化,如原型bean(作用域設(shè)置為prototype的bean)是在需要使用時(shí)初始化的。beanDefinitionMap中的beanDefinition對象相當(dāng)于一個(gè)中轉(zhuǎn)站,存放了bean的所有信息(包含作用域范圍),在初始化時(shí)根據(jù)beanDefinition對象的屬性信息進(jìn)行。8.2SpringIoC容器SpringIoC容器在啟動的過程中,對bean進(jìn)行初始化、實(shí)例化時(shí),大致分為兩步:第一步將class文件轉(zhuǎn)換為beanDefinition對象,第二步根據(jù)beanDefinition對象,按照配置的要求進(jìn)行初始化、實(shí)例化。SpringIoC容器為什么不在掃描到class文件后,立即進(jìn)行初始化、實(shí)例化呢?這是因?yàn)樵赟pring框架提供的容器管理功能中,某些class類并不需要立刻初始化,如原型bean(作用域設(shè)置為prototype的bean)是在需要使用時(shí)初始化的。beanDefinitionMap中的beanDefinition對象相當(dāng)于一個(gè)中轉(zhuǎn)站,存放了bean的所有信息(包含作用域范圍),在初始化時(shí)根據(jù)beanDefinition對象的屬性信息進(jìn)行。8.2SpringIoC容器8.2.3Spring框架中的依賴注入每個(gè)軟件都是由很多“組件”構(gòu)成的。這里的“組件”是指廣義的組件—組成部件,它可能是函數(shù),可能是類,可能是包,也可能是微服務(wù)。軟件的架構(gòu)就是組件和組件之間的關(guān)系;而這些組件和組件之間的關(guān)系,就是廣義的依賴關(guān)系。依賴注入就是將一個(gè)bean和它依賴的對象連接在一起的過程。假如Pen類有write()方法,用來表示筆的書寫功能;Student類有study()方法,用來表示學(xué)生的學(xué)習(xí)動作。下面我們討論學(xué)生學(xué)習(xí)需要用到筆的情況。publicclassPen{

publicvoidwrite(){

System.out.println("penwrite...");

}

}publicclassStudent{

privatePenpen;

publicvoidstudy(){

System.out.println("studentstudy...");

pen.write();

}

}8.2SpringIoC容器這里只定義了Student類與Pen類之間的依賴關(guān)系,但是并沒有給Student類傳入Pen類的實(shí)例對象,直接新建(new)一個(gè)student對象調(diào)用study()方法就會出現(xiàn)NullPointerException異常。要想使代碼正常執(zhí)行,可以繼續(xù)完善Student類的代碼,通過構(gòu)造器參數(shù)及setter()方法注入Pen類的實(shí)例對象。完善后的Student類代碼如下。publicclassStudent{

privatePenpen;

//setter方法和getter方法

publicPengetPen(){

returnpen;

}

publicvoidsetPen(Penpen){

this.pen=pen;

}

//構(gòu)造器方法

publicStudent(){

}

publicStudent(Penpen){

this.pen=pen;

}

publicvoidstudy(){

System.out.println("studentstudy...");

pen.write();

}

}8.2SpringIoC容器接下來編寫一個(gè)測試代碼,學(xué)習(xí)在Java代碼中是如何進(jìn)行依賴注入的。在測試代碼中,首先在testConstructorDI()方法中編寫構(gòu)造器注入的代碼,也就是簡單地在創(chuàng)建對象時(shí)傳入依賴的對象實(shí)例;其次在testSetterDI()方法中編寫Setter注入的代碼,這里通過Setter方法傳入依賴的對象實(shí)例;最后分別在main()函數(shù)中調(diào)用這些方法。測試代碼如下。publicclassTestDemo{

//構(gòu)造器注入測試方法

publicstaticvoidtestConstructorDI(){

Penpen=newPen();

Studentstudent=newStudent(pen);

student.study();

}

//Setter注入測試方法

publicstaticvoidtestSetterDI(){

Penpen=newPen();

Studentstudent=newStudent();

student.setPen(pen);

student.study();

}

//在main()函數(shù)中執(zhí)行測試方法

publicstaticvoidmain(String[]args){

System.out.println("構(gòu)造器注入測試:");

testConstructorDI();

System.out.println("分割線");

System.out.println("Setter方法注入測試:");

testSetterDI();

}

}8.2SpringIoC容器study()方法和write()方法成功執(zhí)行,執(zhí)行結(jié)果如圖8-14所示,可以看到,Java中這種簡單的依賴注入的形式,直接在代碼中將兩個(gè)對象連接在一起。當(dāng)把一個(gè)bean交給SpringIoC容器管理時(shí),它依賴的對象同樣要在構(gòu)造器參數(shù)、對象實(shí)例化之后,通過Setter方法注入其屬性或方法參數(shù)。但是在Spring框架中則不必手動創(chuàng)建對象,而是在配置文件中描述如何創(chuàng)建它們;不必在代碼中直接將對象連接在一起,而是在配置文件中描述哪些對象需要哪些服務(wù),再由SpringIoC容器將它們連接在一起。圖8-14study()方法和write()方法成功執(zhí)行的執(zhí)行結(jié)果8.2SpringIoC容器study()方法和write()方法成功執(zhí)行,執(zhí)行結(jié)果如圖8-14所示,可以看到,Java中這種簡單的依賴注入的形式,直接在代碼中將兩個(gè)對象連接在一起。當(dāng)把一個(gè)bean交給SpringIoC容器管理時(shí),它依賴的對象同樣要在構(gòu)造器參數(shù)、對象實(shí)例化之后,通過Setter方法注入其屬性或方法參數(shù)。但是在Spring框架中則不必手動創(chuàng)建對象,而是在配置文件中描述如何創(chuàng)建它們;不必在代碼中直接將對象連接在一起,而是在配置文件中描述哪些對象需要哪些服務(wù),再由SpringIoC容器將它們連接在一起。圖8-14study()方法和write()方法成功執(zhí)行的執(zhí)行結(jié)果8.3.1構(gòu)造器注入基于構(gòu)造函數(shù)的依賴注入是通過容器調(diào)用具有參數(shù)的構(gòu)造方法,構(gòu)造方法中的每個(gè)參數(shù)都表示一個(gè)依賴項(xiàng)。在Spring框架中,構(gòu)造器可以通過形參名稱、形參位置、形參類型注入依賴。這些注入的參數(shù)可以是基本類型,也可以是引用類型(包含SpringIoC容器中的bean)。8.3依賴注入的3種方式例8-2演示Spring框架中構(gòu)造器注入的基本使用方法。(1)編寫bean的代碼。在src目錄下的org.example.dao包中編輯UserDao類代碼,添加name字段和age字段,添加構(gòu)造方法。publicclassUserDao{

privateStringname;

privateIntegerage;

//省略了getter和setter方法

//獲取用戶列表

publicvoidgetUserList(){

//用打印一段話來模擬獲取用戶列表功能的執(zhí)行

System.out.println("獲取用戶列表...");

}

//構(gòu)造器函數(shù)

publicUserDao(Stringname,Integerage){

this.name=name;

this.age=age;

}

}(2)編寫spring-config.xml配置文件,裝配bean。①方式一:根據(jù)構(gòu)造器的形參名稱形式注入,在XML配置文件中編寫如下代碼。8.3依賴注入的3種方式<beanid="userDao"class="org.example.dao.UserDao">

<constructor-argname="name"value="張三"></constructor-arg>

<constructor-argname="age"value="18"></constructor-arg>

</bean>②方式二:根據(jù)構(gòu)造器的形參位置注入,在XML配置文件中編寫如下代碼。<beanid="userDao"class="org.example.dao.UserDao">

<constructor-argindex="0"value="張三"></constructor-arg>

<constructor-argindex="1"value="18"></constructor-arg>

</bean>③方式三:根據(jù)構(gòu)造器的形參類型注入,在XML配置文件中編寫如下代碼。<beanid="userDao"class="org.example.dao.UserDao">

<constructor-argtype="java.lang.String"value="張三"></constructor-arg>

<constructor-argtype="java.lang.Integer"value="18"></constructor-arg>

</bean>④方式四:注入SpringIoC容器中的其他bean。這里還需要添加其他bean的代碼,以及在UserDao類中添加這個(gè)Bean類型字段,并完善構(gòu)造器方法。在src目錄下的org.example.dao包中添加一個(gè)OrderDao類,并在UserDao類中添加一個(gè)OrderDao類,以及一個(gè)含OrderDao參數(shù)的構(gòu)造器方法。8.3依賴注入的3種方式publicclassUserDao{

privateStringname;

privateIntegerage;

privateOrderDaoorderDao;

//

添加字段

//省略getter和setter方法

//

省略userDao原有方法

//添加包含orderDao字段的構(gòu)造器方法

publicUserDao(Stringname,Integerage,OrderDaoorderDao){

this.name=name;

this.age=age;

this.orderDao=orderDao;

}

}publicclassOrderDao{

//創(chuàng)建訂單方法

publicvoidcreateOrder(){

//使用輸出語句模擬創(chuàng)建訂單功能

System.out.println("創(chuàng)建訂單...");

}

}在spring-config.xml配置文件中裝配OrderDao類和UserDao類,在裝配UserDao類時(shí)使用含OrderDao字段的構(gòu)造器方法,代碼如下。8.3依賴注入的3種方式<beanid="orderDao"class="org.example.dao.OrderDao"></bean>

<beanid="userDao"class="org.example.dao.UserDao">

<constructor-argname="name"value="張三"></constructor-arg>

<constructor-argname="age"value="18"></constructor-arg>

<constructor-argname="orderDao"ref="orderDao"></constructor-arg>

</bean>publicclassTest1{

publicstaticvoidmain(String[]args){

//創(chuàng)建SpringIoC容器:讀取類目錄下的配置文件

ApplicationContextcontext=newClassPathXmlApplicationContext("spring-config.xml");

//從SpringIoC容器中獲取bean

UserDaouserDao=context.getBean(UserDao.class);

userDao.getUserList();

System.out.println(userDao.getName());

System.out.println(userDao.getAge());

//執(zhí)行OrderDao中方法

OrderDaoorderDao=userDao.getOrderDao();

orderDao.createOrder();

}

}測試代碼執(zhí)行結(jié)果8.3.2Setter注入基于Setter方法的依賴注入(Setter注入)是指通過bean中的Setter方法給對象注入依賴項(xiàng)。首先,在bean中需要保證有Setter方法來接受注入的依賴對象,其次,在Spring框架的XML配置文件中的bean標(biāo)簽下,通過property標(biāo)簽描述依賴注入的方式。8.3依賴注入的3種方式例8-3演示Spring框架中Setter注入的基本使用方法。(1)編寫bean的代碼。以org.example.dao包中的UserDao類為例,補(bǔ)充UserDao類中各字段的Setter方法和Getter方法,代碼如下。publicclassUserDao{

privateStringname;

privateIntegerage

privateOrderDaoorderDao;

//省略getter和settter方法

//獲取用戶列表

publicvoidgetUserList(){

//用打印一段話來模擬獲取用戶列表功能的執(zhí)行

System.out.println(“獲取用戶列表...”);

}

//補(bǔ)充無參構(gòu)造器函數(shù)

publicUserDao(){

}

}(2)編寫spring-config.xml配置文件,裝配bean,代碼如下。8.3依賴注入的3種方式<beanid="orderDao"class="org.example.dao.OrderDao"></bean>

<beanid="userDao"class="org.example.dao.UserDao">

<!--使用setter方法注入-->

<propertyname="name"value="張三"></property>

<propertyname="age"value="100"></property>

<propertyname="orderDao"ref="orderDao"></property>

</bean>publicclassTest1{

publicstaticvoidmain(String[]args){

//創(chuàng)建SpringIoC容器:讀取類目錄下的配置文件

ApplicationContextcontext=newClassPathXmlApplicationContext("spring-config.xml");

//從SpringIoC容器中獲取bean

UserDaouserDao=context.getBean(UserDao.class);

userDao.getUserList();

System.out.println(userDao.getName());

System.out.println(userDao.getAge());

//執(zhí)行OrderDao中方法

OrderDaoorderDao=userDao.getOrderDao();

orderDao.createOrder();

}

}測試代碼執(zhí)行結(jié)果8.3.3接口注入接口注入和Setter注入類似,都是通過特定的方法注入被依賴對象,二者的主要區(qū)別為:在Setter注入中,需要在類中實(shí)現(xiàn)Setter方法,并使用Setter方法注入依賴對象,被注入的具體對象是在配置文件中使用<property>標(biāo)簽定義的;而在接口注入中,需要實(shí)現(xiàn)特定的BeanFactoryAware接口,使用該接口提供的setBeanFactory()方法注入依賴對象,被注入的具體對象是在setBeanFactory()方法中定義的。例8-4演示Spring框架中接口注入的基本使用方法。(1)編寫bean的代碼。這里仍使用之前org.example.dao包中創(chuàng)建的OrderDao類,同時(shí)新建一個(gè)UserDao2類實(shí)現(xiàn)BeanFactoryAware接口,并使用setBeanFactory()方法注入依賴對象,代碼如下。8.3依賴注入的3種方式8.3依賴注入的3種方式publicclassUserDao2implementsBeanFactoryAware{

privateStringname;

privateIntegerage;

privateOrderDaoorderDao;

//創(chuàng)建訂單方法

publicvoidcreateOrder(){

//調(diào)用orderDao對象中的方法

this.orderDao.createOrder();

}

@Override

publicvoidsetBeanFactory(BeanFactorybeanFactory)throwsBeansException{

this.name="張三";

this.age=18;

//這里是從容器中獲取bean

OrderDaoorderDao=beanFactory.getBean(OrderDao.class);

this.orderDao=orderDao;

}

}(2)編寫spring-config.xml配置文件,裝配bean,代碼如下。<beanid="orderDao"class="org.example.dao.OrderDao"/>

<beanid="userDao"class="org.example.dao.UserDao2"/>由于UserDao2類已經(jīng)通過BeanFactoryAware接口的setBeanFactory()方法注入了依賴,所以這里只需要進(jìn)行bean的裝配。(3)編寫測試代碼。在測試代碼中創(chuàng)建容器,并從SpringIoC容器中獲取userDao2對象,然后調(diào)用createOrder()方法,代碼如下。8.3依賴注入的3種方式publicclassTest2{

publicstaticvoidmain(String[]args){

//創(chuàng)建容器

ApplicationContextcontext=newClassPathXmlApplicationContext("spring-config.xml");

//從容器中獲取Bean

UserDao2userDao2=context.getBean(UserDao2.class);

//執(zhí)行Bean中的方法

userDao2.createOrder();

}

}圖8-15createOrder()方法成功執(zhí)行的執(zhí)行結(jié)果createOrder()方法成功執(zhí)行,執(zhí)行結(jié)果如圖8-15所示,使用接口注入方式并沒有在XML配置文件中定義依賴關(guān)系,可見通過BeanFactoryAware接口使用setBeanFactory()方法同樣能夠完成依賴的注入。這種方法的依賴注入是硬編碼在bean中的,侵入性較強(qiáng),在項(xiàng)目開發(fā)中使用較少,了解即可。8.4.1作用域的分類Spring框架中主要有5種類型的作用域,分別是singleton、prototype、request、session、global-session。Spring框架中的作用域描述如表8-1所示。8.4bean的作用域作用域描述singleton默認(rèn)作用域,將bean的作用域定義為在SpringIoC容器中以單例形式存在prototype將bean的作用域定義為在SpringIoC容器中以多例形式存在request將bean的作用域定義為在一個(gè)HTTP請求的生命周期內(nèi)有效。每次HTTP請求后都會創(chuàng)建一個(gè)新的bean,僅用于WebApplicationContext環(huán)境session將bean的作用域定義為在一個(gè)HTTP會話的生命周期內(nèi)有效。同一個(gè)HTTP會話共享一個(gè)bean,僅用于WebApplicationContext環(huán)境global-session類似于標(biāo)準(zhǔn)的HTTPSession作用域,不過它僅在基于portlet的Web應(yīng)用程序中才有意義表8-1Spring框架中的作用域描述8.4.2singletonsingleton是Spring框架中默認(rèn)的作用域,若在bean標(biāo)簽中沒有定義scope屬性,則Spring框架默認(rèn)會以單例模式創(chuàng)建bean。單例模式就是采取一定的方法保證在整個(gè)軟件系統(tǒng)中,某個(gè)類只能存在一個(gè)對象實(shí)例,且該類只提供一個(gè)取得其實(shí)例的方法。在Java中定義一個(gè)簡單的單例類需要以下步驟:①私有化構(gòu)造器;②在類內(nèi)部創(chuàng)建對象實(shí)例;③提供一個(gè)共有的靜態(tài)方法返回實(shí)例對象。8.4bean的作用域classSingleton{

//構(gòu)造器私有化

privateSingleton(){

}

//在本類內(nèi)部創(chuàng)建對象實(shí)例

privatefinalstaticSingletoninstance=newSingleton();

//提供一個(gè)公有的靜態(tài)方法,返回實(shí)例對象

publicstaticSingletongetInstance(){

returninstance;

}

}例8-5演示Java中單例類的創(chuàng)建。(1)編寫單例類Singleton,代碼如下。(2)測試代碼如下。首先定義一個(gè)測試方法,多次獲取Singleton類的實(shí)例,其次打印輸出對象的地址值。測試代碼運(yùn)行結(jié)果如圖8-16所示,singleton1和singleton2輸出的對象地址值相同,這就表示這里的類是單例類,創(chuàng)建的對象是單例對象。8.4bean的作用域publicclassTest3{

publicstaticvoidmain(String[]args){

Singletonsingleton1=Singleton.getInstance();

Singletonsingleton2=Singleton.getInstance();

System.out.println(singleton1);

System.out.println(singleton2);

}

}圖8-16singleton1和singleton2輸出對象地址值相同Spring框架提供了更為簡潔的創(chuàng)建單例對象的方法,默認(rèn)創(chuàng)建的對象就是單例對象,也可以在bean標(biāo)簽中通過scope屬性設(shè)置為單例模式。例8-6演示Spring框架中單例模式的使用。(1)編寫bean的代碼。這里使用的是之前org.example.dao包中創(chuàng)建的OrderDao類,代碼如下。(2)編寫spring-config.xml配置文件,裝配bean。8.4bean的作用域publicclassOrderDao{

//創(chuàng)建訂單方法

publicvoidcreateOrder(){

//使用輸出語句來模擬創(chuàng)建訂單功能

System.out.println("創(chuàng)建訂單...");

}

}<!--默認(rèn)是單例作用域-->

<beanid="orderDao"class="org.example.dao.OrderDao"></bean><!--顯式聲明scope為單例作用域-->

<beanid="orderDao"class="org.example.dao.OrderDao"

scope="singleton"></bean>或者(3)測試代碼如下。測試代碼運(yùn)行結(jié)果如圖8-17所示,orderDao1和orderDao2輸出的對象地址值相同,可見兩次從SpringIoC容器中獲取的orderDao對象是同一個(gè)(引用地址值相同)。8.4bean的作用域publicclassTest3{

publicstaticvoidmain(String[]args){

ApplicationContextcontext=newClassPathXmlApplicationContext("spring-config.xml");

OrderDaoorderDao1=context.getBean(OrderDao.class);

OrderDaoorderDao2=context.getBean(OrderDao.class);

System.out.println(orderDao1);

System.out.println(orderDao2);

}

}圖8-17orderDao1和orderDao2輸出對象地址值相同8.4.3prototypeprototype作用域會將bean定義為在SpringIoC容器中以多例形式存在的對象,即每次從SpringIoC容器中獲取prototype作用域的bean時(shí),都會創(chuàng)建一個(gè)新的實(shí)例。在XML配置文件的bean標(biāo)簽中將scope屬性設(shè)置為prototype,就表示這個(gè)bean是多例的。8.4bean的作用域例8-7演示Spring框架中的prototype作用域。(1)編寫bean的代碼。這里仍然使用之前org.example.dao包中創(chuàng)建的OrderDao類。(2)編寫spring-config.xml配置文件,裝配bean。publicclassOrderDao{

//創(chuàng)建訂單方法

publicvoidcreateOrder(){

//使用輸出語句來模擬創(chuàng)建訂單功能

System.out.println("創(chuàng)建訂單...");

}

}<!--聲明scope為prototype作用域-->

<beanid="orderDao"class="org.example.dao.OrderDao"scope="prototype"></bean>(3)測試代碼如下。測試代碼運(yùn)行結(jié)果如圖8-18所示,orderDao1和orderDao2輸出的對象的地址值不同,可見設(shè)置scope為prototype后,從SpringIoC容器中多次獲取的對象不是同一個(gè)(引用地址值不同)。8.4bean的作用域publicclassTest3{

publicstaticvoidmain(String[]args){

ApplicationContextcontext=newClassPathXmlApplicationContext("spring-config.xml");

OrderDaoorderDao1=context.getBean(OrderDao.class);

OrderDaoorderDao2=context.getBean(OrderDao.class);

System.out.println(orderDao1);

System.out.println(orderDao2);

}

}圖8-18orderDao1和orderDao2輸出的對象的地址值不同8.5.1基于XML裝配beanSpring框架基本的XML配置文件可以在beans標(biāo)簽內(nèi)添加bean標(biāo)簽來裝配bean。bean標(biāo)簽的常用屬性說明如表8-2所示。8.5Spring框架中bean的裝配方式屬性名稱說明idbean的唯一標(biāo)識名,必須以字母開頭,且不能包含特殊字符name用來為bean指定一個(gè)或多個(gè)別名,且能包含特殊字符。若bean沒有id,則name可被當(dāng)作id使用class用來定義類的全限定名(包名+類名)。scope設(shè)置bean的作用域init-methodbean的初始化方法,在對象創(chuàng)建時(shí)被調(diào)用destroy-methodbean的銷毀方法,在對象被銷毀或容器關(guān)閉時(shí)被調(diào)用factory-bean配置bean工廠的實(shí)例對象factory-method配置bean的工廠方法表8-2bean標(biāo)簽的常用屬性說明bean標(biāo)簽內(nèi)有constructor-arg標(biāo)簽和property標(biāo)簽:constructor-arg標(biāo)簽通過構(gòu)造器進(jìn)行依賴注入,常用的屬性說明如表8-3所示。property標(biāo)簽上常用的屬性有name、ref、value,使用方式與在constructor-arg標(biāo)簽上的相同。8.5Spring框架中bean的裝配方式屬性名稱說明name構(gòu)造器注入時(shí)按照形參名稱注入type構(gòu)造器注入時(shí)按照形參類型注入index構(gòu)造器注入時(shí)按照形參位置注入ref注入已經(jīng)在SpringIoC容器中的bean對象value要注入的屬性值表8-3constructor-arg標(biāo)簽上常用的屬性說明例8-8演示bean標(biāo)簽中init-method、destroy-method、factory-method屬性的使用。(1)編寫bean的代碼。這里仍然使用之前org.example.dao包中創(chuàng)建的OrderDao類,添加了init()初始化方法、destroy()銷毀方法及getOrderDao()工廠方法,代碼如下。(2)編寫spring-config.xml配置文件,裝配bean。8.5Spring框架中bean的裝配方式publicclassOrderDao{

//創(chuàng)建訂單方法

publicvoidcreateOrder(){

//使用輸出語句模擬創(chuàng)建訂單功能

System.out.println("創(chuàng)建訂單...");

}

//初始化方法

publicvoidinit(){

System.out.println("初始化方法...");

}

//銷毀方法

publicvoiddestroy(){

System.out.println("銷毀方法...");

}

//創(chuàng)建OrderDao對象的工廠方法

publicstaticOrderDaogetOrderDao(){

System.out.println("getOrderDao方法執(zhí)行...");

returnnewOrderDao();

}

}<beanid="orderDao"class="org.example.dao.OrderDao"init-method="init"destroy-method="destroy"

factory-method="getOrderDao"></bean>(3)測試代碼如下。在這個(gè)測試代碼中創(chuàng)建了容器,獲取了orderDao對象,然后使用close()方法關(guān)閉了容器。測試代碼運(yùn)行結(jié)果如圖8-19所示,init()方法、destroy()方法和getOrderDao()方法成功執(zhí)行,可見這里Spring框架通過factory-method方法指定的工廠方法創(chuàng)建orderDao對象,并且在創(chuàng)建對象時(shí)執(zhí)行了init-method指定的初始化方法,在容器關(guān)閉時(shí)執(zhí)行了destroy-method指定的銷毀方法。8.5Spring框架中bean的裝配方式publicclassTest4{

publicstaticvoidmain(String[]args){

ClassPathXmlApplicationContextcontext=newClassPathXmlApplicationContext("spring-config.xml");

OrderDaoorderDao=context.getBean(OrderDao.class);

//關(guān)閉容器,使orderDao對象中的銷毀方法能夠觸發(fā)

context.close();

}

}圖8-19測試代碼運(yùn)行結(jié)果8.5.2基于組件掃描注解裝配beanSpring框架支持基于組件掃描注解裝配bean的方式,通過裝配bean相關(guān)的注解@Component,可以簡化配置,提升開發(fā)效率。要使Spring框架能夠識別相應(yīng)的注解,需要配置組件掃描,有通過XML配置文件開啟組件掃描和基于Java配置類開啟組件掃描兩種方式。(1)方式一:通過XML配置文件開啟組件掃描。例8-9演示通過XML配置文件開啟組件掃描。①編寫bean的代碼。這里在org.example.dao包中創(chuàng)建了兩個(gè)簡單的bean,然后分別在UserDao類及OrderDao類上添加@Component注解,表明在掃描Spring組件時(shí)要將這些bean裝配到容器中,代碼如下。8.5Spring框架中bean的裝配方式②編寫spring-config.xml配置文件,開啟組件掃描。在XML配置文件中,通過context:component-scan標(biāo)簽的base-package屬性配置要掃描的包為org.example包,這樣Spring框架會掃描org.example包(包含其子包)下所有配置了裝配相關(guān)注解的bean,代碼如下。8.5Spring框架中bean的裝配方式<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="/schema/beans"

xmlns:xsi="/2001/XMLSchema-instance"

xmlns:context="/schema/context"

xsi:schemaLocation="/schema/beans

/schema/beans/spring-beans.xsd

/schema/context

/schema/context/spring-context.xsd">

<!--開啟組件掃描,配置要掃描的包為org.example包-->

<context:component-scanbase-package="org.example"/>

</beans>@Component

publicclassOrderDao{

publicvoidcreateOrder(){

System.out.println("創(chuàng)建訂單...");

}

}@Component

publicclassUserDao{

publicvoidcreateUser(){

System.out.println("創(chuàng)建用戶...");

}

}

注意,這里要使用context系列的標(biāo)簽,就需要添加對應(yīng)的xsd約束。③測試代碼如下。測試代碼運(yùn)行結(jié)果如圖8-20所示,createUser()方法和createOrder()方法成功執(zhí)行。從測試結(jié)果來看,UserDao類和OrderDao類中的方法都能夠正常執(zhí)行。我們只在XML配置文件中開啟了組件掃描,以及在要裝配的bean上使用了注解,這種基于組件掃描注解的方式很大程度上簡化了開發(fā),讓我們不必在XML配置文件中進(jìn)行煩瑣的裝配操作。8.5Spring框架中bean的裝配方式publicclassSpringDemoTest{

publicstaticvoidmain(String[]args){

//創(chuàng)建容器

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論