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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

spring----06 更多DI知识

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

一. 延遲初始化

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

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

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

二. 使用depends-on

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

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

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

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

舉例說明:

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

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

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

說明:

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

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

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容器能自動把字符串轉(zhuǎn)換為java.io.File。

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

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

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

3. 測試

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

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

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

三. 自動裝配

自動裝配就是指由Spring來自動地注入依賴對象,無需人工參與。

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

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

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

1. no

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

2. byName

通過設(shè)置Bean定義屬性autowire="byName",意思是根據(jù)名字進行自動裝配,只能用于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>了,如果一個bean有很多setter注入,通過“byName”方式是不是能減少很多 <property>配置。此處注意了,在根據(jù)名字注入時,將把當(dāng)前Bean自己排除在外:比如“hello”Bean類定義了 “setHello”方法,則hello是不能注入到“setHello”的。

3. byType

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

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

note:

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

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

4. constructor

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

5. 全局自動裝配

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

6. 不是所有類型都能自動裝配

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

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

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

8. 自動裝配的優(yōu)缺點

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

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

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

?

9. 依賴檢查

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

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

依賴檢查有none、simple、object、all四種方式,接下來讓我們詳細(xì)介紹一下:

(1)none

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

(2)objects

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

<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> <!-- 注意我們沒有注入helloApi,所以測試時會報錯 --> <bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" dependency-check="objects"> <property name="message" value="Haha"/> </bean>

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

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

(3)simple

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

<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> <!-- 注意我們沒有注入message屬性,所以測試時會報錯 --> <bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" dependency-check="simple"> <property name="helloApi" ref="helloApi"/> </bean>

(4)all

對所以類型進行依賴檢查,配置方式為:dependency-check="all",如下配置方式中如果兩個屬性其中一個沒配置將報錯。

<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>

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

?

參考文獻:

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

?

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

總結(jié)

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

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