日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

spring----06 更多DI知识

發(fā)布時(shí)間:2023/12/10 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring----06 更多DI知识 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一. 延遲初始化

延遲初始化也叫做惰性初始化,指不提前初始化Bean,而是只有在真正使用時(shí)才創(chuàng)建及初始化Bean。
配置方式很簡(jiǎn)單只需在<bean>標(biāo)簽上指定 lazy-init” 屬性值為“true”即可延遲初始化Bean

? ? ? ?Spring容器會(huì)在創(chuàng)建容器時(shí)提前初始化“singleton”作用域的Bean,“singleton”就是單例的意思即整個(gè)容器 每個(gè)Bean只有一個(gè)實(shí)例,后邊會(huì)詳細(xì)介紹。Spring容器預(yù)先初始化Bean通常能幫助我們提前發(fā)現(xiàn)配置錯(cuò)誤,所以如果 沒(méi)有什么情況建議開啟,除非有某個(gè)Bean可能需要加載很大資源,而且很可能在整個(gè)應(yīng)用程序生命周期中很可能使用不 到,可以設(shè)置為延遲初始化。
延遲初始化的Bean通常會(huì)在第一次使用時(shí)被初始化;或者在被非延遲初始化Bean作為依賴對(duì)象注入時(shí)在會(huì)隨著初 始化該Bean時(shí)被初始化,因?yàn)樵谶@時(shí)使用了延遲初始化Bean。
? ? ? 容器管理初始化Bean消除了編程實(shí)現(xiàn)延遲初始化,完全由容器控制,只需在需要延遲初始化的Bean定義上配置即 可,比編程方式更簡(jiǎn)單,而且是無(wú)侵入代碼的。

<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl" lazy-init="true"/>

二. 使用depends-on

depends-on是指指定Bean初始化及銷毀時(shí)的順序,使用depends-on屬性指定的Bean要先初始化完畢后才初始 化當(dāng)前Bean,由于只有“singleton”Bean能被Spring管理銷毀,所以當(dāng)指定的Bean都是“singleton”時(shí),使用 depends-on屬性指定的Bean要在指定的Bean之后銷毀.

<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> <bean id="decorator" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" depends-on="helloApi"> <property name="helloApi"><ref bean="helloApi"/></property> </bean>

說(shuō)明:“decorator”指定了“depends-on”屬性為“helloApi”,所以在“decorator”Bean初始化之前要先初始化 “helloApi”,而在銷毀“helloApi”之前先要銷毀“decorator”。

“depends-on”屬性可以指定多個(gè)Bean,若指定多個(gè)Bean可以用“;”、“,”、空格分割。

那“depends-on”有什么好處呢?主要是給出明確的初始化及銷毀順序,比如要初始化“decorator”時(shí)要確保 “helloApi”Bean的資源準(zhǔn)備好了,否則使用“decorator”時(shí)會(huì)看不到準(zhǔn)備的資源;而在銷毀時(shí)要先在 “decorator”Bean的把對(duì)“helloApi”資源的引用釋放掉才能銷毀“helloApi”,否則可能銷毀 “helloApi”時(shí)而 “decorator”還保持著資源訪問(wèn),造成資源不能釋放或釋放錯(cuò)誤。

舉例說(shuō)明:

,在平常開發(fā)中我們可能需要訪問(wèn)文件系統(tǒng),而文件打開、關(guān)閉是必須配對(duì)的,不能打開后不關(guān) 閉,從而造成其他程序不能訪問(wèn)該文件。讓我們來(lái)看具體配置吧:

1. 準(zhǔn)備測(cè)試類:

1 public class ResourceBean { 2 private FileOutputStream fos; 3 private File file; 4 //初始化方法 5 public void init() { 6 System.out.println("ResourceBean:========初始化"); 7 //加載資源,在此只是演示 8 System.out.println("ResourceBean:========加載資源,執(zhí)行一些預(yù)操作"); 9 try { 10 this.fos = new FileOutputStream(file); 11 } catch (FileNotFoundException e) { 12 e.printStackTrace(); 13 } 14 } 15 //銷毀資源方法 16 public void destroy() { 17 System.out.println("ResourceBean:========銷毀"); 18 //釋放資源 19 System.out.println("ResourceBean:========釋放資源,執(zhí)行一些清理操作"); 20 try { 21 fos.close(); 22 } catch (IOException e) { 23 e.printStackTrace(); 24 } 25 } 26 public FileOutputStream getFos() { 27 return fos; 28 } 29 public void setFile(File file) { 30 this.file = file; 31 } 32 } View Code 1 public class DependentBean { 2 ResourceBean resourceBean; 3 public void write(String ss) throws IOException { 4 System.out.println("DependentBean:=======寫資源"); 5 resourceBean.getFos().write(ss.getBytes()); 6 } 7 //初始化方法 8 public void init() throws IOException { 9 System.out.println("DependentBean:=======初始化"); 10 resourceBean.getFos().write("DependentBean:=======初始化=====".getBytes()); 11 } 12 //銷毀方法 13 public void destroy() throws IOException { 14 System.out.println("DependentBean:=======銷毀"); 15 //在銷毀之前需要往文件中寫銷毀內(nèi)容 16 resourceBean.getFos().write("DependentBean:=======銷毀=====".getBytes()); 17 } 18 19 public void setResourceBean(ResourceBean resourceBean) { 20 this.resourceBean = resourceBean; 21 } 22 } View Code

說(shuō)明:

ResourceBean從配置文件中配置文件位置,然后定義初始化方法init中打開指定的文件,然后獲取文件流;最后定義銷 毀方法destroy用于在應(yīng)用程序關(guān)閉時(shí)調(diào)用該方法關(guān)閉掉文件流。

DependentBean中會(huì)注入ResourceBean,并從ResourceBean中獲取文件流寫入內(nèi)容;定義初始化方法init用來(lái)定義 一些初始化操作并向文件中輸出文件頭信息;最后定義銷毀方法用于在關(guān)閉應(yīng)用程序時(shí)想文件中輸出文件尾信息。

2. 準(zhǔn)備配置文件

<bean id="resourceBean" class="cn.javass.spring.chapter3.bean.ResourceBean" init-method="init" destroy-method="destroy"> <property name="file" value="D:/test.txt"/> </bean> <bean id="dependentBean" class="cn.javass.spring.chapter3.bean.DependentBean" init-method="init" destroy-method="destroy" depends-on="resourceBean"> <property name="resourceBean" ref="resourceBean"/> </bean>

? ? ?<property name="file" value="D:/test.txt"/>配置:Spring容器能自動(dòng)把字符串轉(zhuǎn)換為java.io.File。

?? ? ?init-method="init"?指定初始化方法,在構(gòu)造器注入和setter注入完畢后執(zhí)行。? ? ?

? ? ? destroy-method="destroy"指定銷毀方法,只有“singleton”作用域能銷毀,“prototype”作用域的一定不能,其他作用域不一定能;后邊再介紹。

在此配置中,resourceBean初始化在dependentBean之前被初始化,resourceBean銷毀會(huì)在dependentBean銷 毀之后執(zhí)行。

3. 測(cè)試

1 public class MoreDependencyInjectTest { 2 @Test 3 public void testDependOn() throws IOException { 4 ClassPathXmlApplicationContext context = 5 new ClassPathXmlApplicationContext("chapter3/depends-on.xml"); 6 //一點(diǎn)要注冊(cè)銷毀回調(diào),否則我們定義的銷毀方法不執(zhí)行 7 context.registerShutdownHook(); 8 DependentBean dependentBean = 9 context.getBean("dependentBean", DependentBean.class); 10 dependentBean.write("aaa"); 11 } 12 } View Code

測(cè)試跟其他測(cè)試完全一樣,只是在此我們一定要注冊(cè)銷毀方法回調(diào),否則銷毀方法不會(huì)執(zhí)行。
如果配置沒(méi)問(wèn)題會(huì)有如下輸出:

1 ResourceBean:========初始化 2 ResourceBean:========加載資源,執(zhí)行一些預(yù)操作 3 DependentBean:=========初始化 4 DependentBean:=========寫資源 5 DependentBean:=========銷毀 6 ResourceBean:========銷毀 7 ResourceBean:========釋放資源,執(zhí)行一些清理操作 View Code

三. 自動(dòng)裝配

自動(dòng)裝配就是指由Spring來(lái)自動(dòng)地注入依賴對(duì)象,無(wú)需人工參與。

目前Spring3.0支持“no”、“byName ”、“byType”、“constructor”四種自動(dòng)裝配,默認(rèn)是“no”指不支 持自動(dòng)裝配的,其中Spring3.0已不推薦使用之前版本的“autodetect”自動(dòng)裝配,推薦使用Java 5+支持的 (@Autowired)注解方式代替;如果想支持“autodetect”自動(dòng)裝配,請(qǐng)將schema改為“spring-beans-2.5.xsd” 或去掉

自動(dòng)裝配的好處是減少構(gòu)造器注入和setter注入配置,減少配置文件的長(zhǎng)度。自動(dòng)裝配通過(guò)配置<bean>標(biāo)簽的 “autowire”屬性來(lái)改變自動(dòng)裝配方式。接下來(lái)讓我們挨著看下配置的含義。

表示使用默認(rèn)的自動(dòng)裝配,默認(rèn)的自動(dòng)裝配需要在<beans>標(biāo)簽中使用default-autowire屬性指 定,其支持“no”、“byName ”、“byType”、“constructor”四種自動(dòng)裝配,如果需要覆蓋默認(rèn)自動(dòng)裝配,請(qǐng) 繼續(xù)往下看;

1. no

意思是不支持自動(dòng)裝配,必須明確指定依賴。

2. byName

通過(guò)設(shè)置Bean定義屬性autowire="byName",意思是根據(jù)名字進(jìn)行自動(dòng)裝配,只能用于setter注 入。比如我們有方法“setHelloApi”,則“byName”方式Spring容器將查找名字為helloApi的Bean并注入,如果找 不到指定的Bean,將什么也不注入。

<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> <bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" autowire="byName"/> note:這里的byName的意思是上面的bean id="helloApi"必須和HelloApiDecorator類中的依賴類HelloImpl的名字一致,private HelloImpl helloApi; 1 public class AutowireBeanTest { 2 @Test 3 public void testAutowireByName() throws IOException { 4 ClassPathXmlApplicationContext context = 5 new ClassPathXmlApplicationContext("chapter3/autowire-byName.xml"); 6 HelloApi helloApi = context.getBean("bean", HelloApi.class); 7 helloApi.sayHello(); 8 } 9 } View Code

是不是不要配置<property>了,如果一個(gè)bean有很多setter注入,通過(guò)“byName”方式是不是能減少很多 <property>配置。此處注意了,在根據(jù)名字注入時(shí),將把當(dāng)前Bean自己排除在外:比如“hello”Bean類定義了 “setHello”方法,則hello是不能注入到“setHello”的。

3. byType

通過(guò)設(shè)置Bean定義屬性autowire="byType",意思是指根據(jù)類型注入,用于setter注入,比如 如果指定自動(dòng)裝配方式為“byType”,而“setHelloApi”方法需要注入HelloApi類型數(shù)據(jù),則Spring容器將查找 HelloApi類型數(shù)據(jù),如果找到一個(gè)則注入該Bean,如果找不到將什么也不注入,如果找到多個(gè)Bean將優(yōu)先注入 <bean>標(biāo)簽“primary”屬性為true的Bean,否則拋出異常來(lái)表明有個(gè)多個(gè)Bean發(fā)現(xiàn)但不知道使用哪個(gè)。讓我們用例 子來(lái)講解一下這幾種情況吧。

在根據(jù)類型注入時(shí),將把當(dāng)前Bean自己排除在外(note:byType時(shí),就不需要helloApi必須和依賴屬性名一樣了,只和類型有關(guān)系,因此將上面的例子中byName改成byType就可以直接運(yùn)行了)

note:

通過(guò)設(shè)置Bean定義的“autowire-candidate”屬性為false來(lái)把指定Bean后自動(dòng)裝配候選者中移除:

<bean class="cn.javass.spring.chapter2.helloworld.HelloImpl" autowire-candidate="false"/>

4. constructor

:通過(guò)設(shè)置Bean定義屬性autowire="constructor",功能和“byType”功能一樣,根據(jù)類 型注入構(gòu)造器參數(shù),只是用于構(gòu)造器注入方式,直接將上面例子的byName改成constructor就好了

5. 全局自動(dòng)裝配

可以采用在“<beans>”標(biāo)簽中通過(guò)“default-autowire”屬性指定全局的自動(dòng)裝配方式,即如果defaultautowire=”byName”,將對(duì)所有Bean進(jìn)行根據(jù)名字進(jìn)行自動(dòng)裝配。

6. 不是所有類型都能自動(dòng)裝配

  • 不能自動(dòng)裝配的數(shù)據(jù)類型:Object、基本數(shù)據(jù)類型(Date、CharSequence、Number、URI、URL、Class、int)等;
  • 通過(guò)“<beans>”標(biāo)簽default-autowire-candidates屬性指定的匹配模式,不匹配的將不能作為自動(dòng)裝配的候選者,例如指定“*Service,*Dao”,將只把匹配這些模式的Bean作為候選者,而不匹配的不會(huì)作為候選者;
  • 通過(guò)將“<bean>”標(biāo)簽的autowire-candidate屬性可被設(shè)為false,從而該Bean將不會(huì)作為依賴注入的候選者。

7.?數(shù)組、集合、字典類型的根據(jù)類型自動(dòng)裝配和普通類型的自動(dòng)裝配是有區(qū)別的:

  • 數(shù)組類型、集合(Set、Collection、List)接口類型:將根據(jù)泛型獲取匹配的所有候選者并注入到數(shù)組或集合中,如“List<HelloApi> list”將選擇所有的HelloApi類型Bean并注入到list中,而對(duì)于集合的具體類型將只選擇一個(gè)候選者,“如 ArrayList<HelloApi> list”將選擇一個(gè)類型為ArrayList的Bean注入,而不是選擇所有的HelloApi類型Bean進(jìn)行注入;
  • 字典(Map)接口類型:同樣根據(jù)泛型信息注入,鍵必須為String類型的Bean名字,值根據(jù)泛型信息獲取,如“Map<String, HelloApi> map” 將選擇所有的HelloApi類型Bean并注入到map中,而對(duì)于具體字典類型如“HashMap<String, HelloApi> map”將只選擇類型為HashMap的Bean注入,而不是選擇所有的HelloApi類型Bean進(jìn)行注入。

8. 自動(dòng)裝配的優(yōu)缺點(diǎn)

? ? ? 優(yōu)點(diǎn):首先,自動(dòng)裝配確實(shí)減少了配置文件的量;其次, “byType”自動(dòng)裝配能在相應(yīng)的Bean更改了字段類型時(shí)自動(dòng)更新,即修改Bean類不需要修改配置,確實(shí)簡(jiǎn)單了。

? ? ? ?缺點(diǎn):最重要的缺點(diǎn)就是沒(méi)有了配置,在查找注入錯(cuò)誤時(shí)非常麻煩,還有比如基本類型沒(méi)法完成自動(dòng)裝配,所以可能經(jīng)常發(fā)生一些莫名其妙的錯(cuò)誤,在此我推薦大家不要使用該方式,最好是指定明確的注入方式,或者采用最新的Java5+注解注入方式。所以大家在使用自動(dòng)裝配時(shí)應(yīng)該考慮自己負(fù)責(zé)項(xiàng)目的復(fù)雜度來(lái)進(jìn)行衡量是否選擇自動(dòng)裝配方式。

?????? 自動(dòng)裝配注入方式能和配置注入方式一同工作嗎?當(dāng)然可以,大家只需記住配置注入的數(shù)據(jù)會(huì)覆蓋自動(dòng)裝配注入的數(shù)據(jù)。

?

9. 依賴檢查

上一節(jié)介紹的自動(dòng)裝配,很可能發(fā)生沒(méi)有匹配的Bean進(jìn)行自動(dòng)裝配,如果此種情況發(fā)生,只有在程序運(yùn)行過(guò)程中 發(fā)生了空指針異常才能發(fā)現(xiàn)錯(cuò)誤,如果能提前發(fā)現(xiàn)該多好啊,這就是依賴檢查的作用。

依賴檢查:用于檢查Bean定義的屬性都注入數(shù)據(jù)了,不管是自動(dòng)裝配的還是配置方式注入的都能檢查,如果沒(méi)有注入數(shù) 據(jù)將報(bào)錯(cuò),從而提前發(fā)現(xiàn)注入錯(cuò)誤,只檢查具有setter方法的屬性。
Spring3+也不推薦配置方式依賴檢查了,建議采用Java5+ @Required注解方式,測(cè)試時(shí)請(qǐng)將XML schema降低為2.5 版本的,和自動(dòng)裝配中“autodetect”配置方式的xsd一樣。

依賴檢查有none、simple、object、all四種方式,接下來(lái)讓我們?cè)敿?xì)介紹一下:

(1)none

默認(rèn)方式,表示不檢查

(2)objects

:檢查除基本類型外的依賴對(duì)象,配置方式為:dependency-check="objects",此處我們?yōu)?HelloApiDecorator添加一個(gè)String類型屬性“message”,來(lái)測(cè)試如果有簡(jiǎn)單數(shù)據(jù)類型的屬性為null,也不報(bào)錯(cuò);

<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> <!-- 注意我們沒(méi)有注入helloApi,所以測(cè)試時(shí)會(huì)報(bào)錯(cuò) --> <bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" dependency-check="objects"> <property name="message" value="Haha"/> </bean>

注意由于我們沒(méi)有注入bean需要的依賴“helloApi”,所以應(yīng)該拋出異常UnsatisfiedDependencyException,表示沒(méi)有發(fā)現(xiàn)滿足的依賴:

public class DependencyCheckTest { @Test(expected = UnsatisfiedDependencyException.class) public void testDependencyCheckByObject() throws IOException { //將拋出異常 new ClassPathXmlApplicationContext("chapter3/dependency-check-object.xml"); } }

(3)simple

對(duì)基本類型進(jìn)行依賴檢查,包括數(shù)組類型,其他依賴不報(bào)錯(cuò);配置方式為:dependency-check="simple",以下配置中沒(méi)有注入message屬性,所以會(huì)拋出異常:

<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> <!-- 注意我們沒(méi)有注入message屬性,所以測(cè)試時(shí)會(huì)報(bào)錯(cuò) --> <bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" dependency-check="simple"> <property name="helloApi" ref="helloApi"/> </bean>

(4)all

對(duì)所以類型進(jìn)行依賴檢查,配置方式為:dependency-check="all",如下配置方式中如果兩個(gè)屬性其中一個(gè)沒(méi)配置將報(bào)錯(cuò)。

<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> <bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" dependency-check="all"> <property name="helloApi" ref="helloApi"/> <property name="message" value="Haha"/> </bean>

依賴檢查也可以通過(guò)“<beans>”標(biāo)簽中default-dependency-check屬性來(lái)指定全局依賴檢查配置。

?

參考文獻(xiàn):

https://jinnianshilongnian.iteye.com/blog/1415461

?

轉(zhuǎn)載于:https://www.cnblogs.com/Hermioner/p/10193125.html

總結(jié)

以上是生活随笔為你收集整理的spring----06 更多DI知识的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。