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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

【Spring学习笔记】之【3.3 DI的深入 二】

發布時間:2025/7/14 javascript 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Spring学习笔记】之【3.3 DI的深入 二】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

3.3.4 ?依賴檢查

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


依賴檢查:用于檢查Bean定義的屬性都注入數據了,不管是自動裝配的還是配置方式注入的都能檢查,如果沒有注入數據將報錯,從而提前發現注入錯誤,只檢查具有setter方法的屬性。

Spring3+也不推薦配置方式依賴檢查了,建議采用Java5+ @Required注解方式,測試時請將XML schema降低為2.5版本的,和自動裝配中“autodetect”配置方式的xsd一樣。


java代碼:查看復制到剪貼板打印
  • <?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

  • </beans> ?


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


    一、none默認方式,表示不檢查;


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


    java代碼:查看復制到剪貼板打印
  • <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”,所以應該拋出異常UnsatisfiedDependencyException,表示沒有發現滿足的依賴:


    java代碼:查看復制到剪貼板打印
  • package cn.javass.spring.chapter3; ?

  • import java.io.IOException; ?

  • import org.junit.Test; ?

  • import org.springframework.beans.factory.UnsatisfiedDependencyException; ?

  • import org.springframework.context.support.ClassPathXmlApplicationContext; ?

  • publicclass DependencyCheckTest { ?

  • @Test(expected = UnsatisfiedDependencyException.class) ?

  • publicvoid testDependencyCheckByObject() throws IOException { ?

  • //將拋出異常

  • new ClassPathXmlApplicationContext("chapter3/dependency-check-object.xml"); ?

  • ? ?} ?

  • } ?


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


    java代碼:查看復制到剪貼板打印
  • <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> ?


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


    java代碼:查看復制到剪貼板打印
  • <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>”標簽中default-dependency-check屬性來指定全局依賴檢查配置。

    3.3.5 方法注入

    所謂方法注入其實就是通過配置方式覆蓋或攔截指定的方法,通常通過代理模式實現。Spring提供兩種方法注入:查找方法注入和方法替換注入。

    因為Spring是通過CGLIB動態代理方式實現方法注入,也就是通過動態修改類的字節碼來實現的,本質就是生成需方法注入的類的子類方式實現。

    在進行測試之前,我們需要確保將“com.springsource.cn.sf.cglib-2.2.0.jar”放到lib里并添加到“Java Build Path”中的Libararies中。否則報錯,異常中包含nested exception is java.lang.NoClassDefFoundError: cn/sf/cglib/proxy/CallbackFilter

    ? ? ? 傳統方式和Spring容器管理方式唯一不同的是不需要我們手動生成子類,而是通過配置方式來實現;其中如果要替換createPrinter()方法的返回值就使用查找方法注入;如果想完全替換sayHello()方法體就使用方法替換注入。 ? ? ? 接下來讓我們看看具體實現吧。


    一、查找方法注入:又稱為Lookup方法注入,用于注入方法返回結果,也就是說能通過配置方式替換方法返回結果。使用<lookup-method name="方法名" bean="bean名字"/>配置;其中name屬性指定方法名,bean屬性指定方法需返回的Bean。

    方法定義格式:訪問級別必須是public或protected,保證能被子類重載,可以是抽象方法,必須有返回值,必須是無參數方法,查找方法的類和被重載的方法必須為非final:

    <public|protected> [abstract] <return-type> theMethodName(no-arguments);


    因為“singleton”Bean在容器中只有一個實例,而“prototype”Bean是每次獲取容器都返回一個全新的實例,所以如果“singleton”Bean在使用“prototype” Bean情況時,那么“prototype”Bean由于是“singleton”Bean的一個字段屬性,所以獲取的這個“prototype”Bean就和它所在的“singleton”Bean具有同樣的生命周期,所以不是我們所期待的結果。因此查找方法注入就是用于解決這個問題。


    1) ?首先定義我們需要的類,Printer類是一個有狀態的類,counter字段記錄訪問次數:


    java代碼:查看復制到剪貼板打印
  • package cn.javass.spring.chapter3.bean; ?

  • publicclass Printer { ?

  • privateint counter = 0; ?

  • publicvoid print(String type) { ?

  • ? ? ? ?System.out.println(type + " printer: " + counter++); ?

  • ? ?} ?

  • } ?


  • ? ? ? HelloImpl5類用于打印歡迎信息,其中包括setter注入和方法注入,此處特別需要注意的是該類是抽象的,充分說明了需要容器對其進行子類化處理,還定義了一個抽象方法createPrototypePrinter用于創建“prototype”Bean,createSingletonPrinter方法用于創建“singleton”Bean,此處注意方法會被Spring攔截,不會執行方法體代碼:


    java代碼:查看復制到剪貼板打印
  • package cn.javass.spring.chapter3; ?

  • import cn.javass.spring.chapter2.helloworld.HelloApi; ?

  • import cn.javass.spring.chapter3.bean.Printer; ?

  • publicabstractclass HelloImpl5 implements HelloApi { ?

  • private Printer printer; ?

  • publicvoid sayHello() { ?

  • ? ? ? ?printer.print("setter"); ?

  • ? ? ? ?createPrototypePrinter().print("prototype"); ?

  • ? ? ? ?createSingletonPrinter().print("singleton");

  • ? ?} ?

  • publicabstract Printer createPrototypePrinter(); ?

  • public Printer createSingletonPrinter() { ?

  • ? ? ? ?System.out.println("該方法不會被執行,如果輸出就錯了"); ?

  • returnnew Printer(); ?

  • ? ?} ?

  • publicvoid setPrinter(Printer printer) { ?

  • this.printer = printer; ?

  • ? ?} ?

  • } ?


  • 2) ?開始配置了,配置文件在(resources/chapter3/lookupMethodInject.xml),其中“prototypePrinter”是“prototype”Printer,“singletonPrinter”是“singleton”Printer,“helloApi1”是“singleton”Bean,而“helloApi2”注入了“prototype”Bean:


    java代碼:查看復制到剪貼板打印
  • <bean id="prototypePrinter"

  • class="cn.javass.spring.chapter3.bean.Printer" scope="prototype"/> ?

  • <bean id="singletonPrinter"

  • class="cn.javass.spring.chapter3.bean.Printer" scope="singleton"/> ?

  • <bean id="helloApi1"class="cn.javass.spring.chapter3.HelloImpl5" scope="singleton"> ?

  • <property name="printer" ref="prototypePrinter"/> ?

  • <lookup-method name="createPrototypePrinter" bean="prototypePrinter"/> ?

  • <lookup-method name="createSingletonPrinter" bean="singletonPrinter"/> ?

  • </bean> ? ? ? ? ? ?

  • <bean id="helloApi2"class="cn.javass.spring.chapter3.HelloImpl5" scope="prototype"> ?

  • <property name="printer" ref="prototypePrinter"/> ?

  • <lookup-method name="createPrototypePrinter" bean="prototypePrinter"/> ?

  • <lookup-method name="createSingletonPrinter" bean="singletonPrinter"/> ?

  • </bean> ? ? ? ? ? ?


  • ? ? ? 3)測試代碼如下:


    java代碼:查看復制到剪貼板打印
  • package cn.javass.spring.chapter3; ?

  • import org.junit.Test; ?

  • import org.springframework.context.support.ClassPathXmlApplicationContext; ?

  • import cn.javass.spring.chapter2.helloworld.HelloApi; ?

  • publicclass MethodInjectTest { ?

  • @Test

  • publicvoid testLookup() { ?

  • ClassPathXmlApplicationContext context = ?

  • new ClassPathXmlApplicationContext("chapter3/lookupMethodInject.xml"); ?

  • ? ? ? ?System.out.println("=======singleton sayHello======"); ?

  • ? ? ? ?HelloApi helloApi1 = context.getBean("helloApi1", HelloApi.class); ?

  • ? ? ? ?helloApi1.sayHello(); ?

  • ? ? ? ?helloApi1 = context.getBean("helloApi1", HelloApi.class); ?

  • ? ? ? ?helloApi1.sayHello(); ?

  • ? ? ? ?System.out.println("=======prototype sayHello======"); ?

  • ? ? ? ?HelloApi helloApi2 = context.getBean("helloApi2", HelloApi.class); ?

  • ? ? ? ?helloApi2.sayHello(); ?

  • ? ? ? ?helloApi2 = context.getBean("helloApi2", HelloApi.class); ?

  • ? ? ? ?helloApi2.sayHello(); ?

  • }} ?


  • ? ? ? 其中“helloApi1”測試中,其輸出結果如下:


    java代碼:查看復制到剪貼板打印
  • =======singleton sayHello====== ?

  • setter printer: 0

  • prototype printer: 0

  • singleton printer: 0

  • setter printer: 1

  • prototype printer: 0

  • singleton printer: 1


  • ? ? ? 首先“helloApi1”是“singleton”,通過setter注入的“printer”是“prototypePrinter”,所以它應該輸出“setter printer:0”和“setter printer:1”;而“createPrototypePrinter”方法注入了“prototypePrinter”,所以應該輸出兩次“prototype printer:0”;而“createSingletonPrinter”注入了“singletonPrinter”,所以應該輸出“singleton printer:0”和“singleton printer:1”。

    ? ? ? 而“helloApi2”測試中,其輸出結果如下:


    java代碼:查看復制到剪貼板打印
  • =======prototype sayHello====== ?

  • setter printer: 0

  • prototype printer: 0

  • singleton printer: 2

  • setter printer: 0

  • prototype printer: 0

  • singleton printer: 3


  • ? ? ? 首先“helloApi2”是“prototype”,通過setter注入的“printer”是“prototypePrinter”,所以它應該輸出兩次“setter printer:0”;而“createPrototypePrinter”方法注入了“prototypePrinter”,所以應該輸出兩次“prototype printer:0”;而“createSingletonPrinter”注入了“singletonPrinter”,所以應該輸出“singleton printer:2”和“singleton printer:3”。

    ? ? ? 大家是否注意到“createSingletonPrinter”方法應該輸出“該方法不會被執行,如果輸出就錯了”,而實際是沒輸出的,這說明Spring攔截了該方法并使用注入的Bean替換了返回結果。

    方法注入主要用于處理“singleton”作用域的Bean需要其他作用域的Bean時,采用Spring查找方法注入方式無需修改任何代碼即能獲取需要的其他作用域的Bean。


    二、替換方法注入:也叫“MethodReplacer”注入,和查找注入方法不一樣的是,他主要用來替換方法體。通過首先定義一個MethodReplacer接口實現,然后如下配置來實現:


    java代碼:查看復制到剪貼板打印
  • <replaced-method name="方法名" replacer="MethodReplacer實現"> ?

  • <arg-type>參數類型</arg-type> ?

  • </replaced-method>” ?

  • ? ? ? 1)首先定義MethodReplacer實現,完全替換掉被替換方法的方法體及返回值,其中reimplement方法重定義方法 功能,參數obj為被替換方法的對象,method為被替換方法,args為方法參數;最需要注意的是不能再 通過“method.invoke(obj, new String[]{"hehe"});” 反射形式再去調用原來方法,這樣會產生循環調用;如果返回值類型為Void,請在實現中返回null:


    java代碼:查看復制到剪貼板打印
  • package cn.javass.spring.chapter3.bean; ?

  • import java.lang.reflect.Method; ?

  • import org.springframework.beans.factory.support.MethodReplacer; ?

  • publicclass PrinterReplacer implements MethodReplacer { ?

  • @Override

  • public Object reimplement(Object obj, Method method, Object[] args) ? throws Throwable { ?

  • ? ? ? ?System.out.println("Print Replacer"); ?

  • //注意此處不能再通過反射調用了,否則會產生循環調用,知道內存溢出

  • //method.invoke(obj, new String[]{"hehe"});

  • returnnull; ?

  • ? ?} ?

  • } ?


  • ? ? ? 2)配置如下,首先定義MethodReplacer實現,使用< replaced-method >標簽來指定要進行替換方法,屬性name指定替換的方法名字,replacer指定該方法的重新實現者,子標簽< arg-type >用來指定原來方法參數的類型,必須指定否則找不到原方法:


    java代碼:查看復制到剪貼板打印
  • <bean id="replacer"class="cn.javass.spring.chapter3.bean.PrinterReplacer"/> ?

  • <bean id="printer"class="cn.javass.spring.chapter3.bean.Printer"> ?

  • <replaced-method name="print" replacer="replacer"> ?

  • ? ? ? ?<arg-type>java.lang.String</arg-type> ?

  • ? ?</replaced-method> ?

  • </bean> ?


  • ? ? ? 3)測試代碼將輸出“Print Replacer ”,說明方法體確實被替換了:


    java代碼:查看復制到剪貼板打印
  • @Test

  • publicvoid testMethodReplacer() { ?

  • ? ?ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("chapter3/methodReplacerInject.xml"); ?

  • ? ?Printer printer = context.getBean("printer", Printer.class); ?

  • ? ?printer.print("我將被替換"); ?

  • } ?



  • 轉載于:https://blog.51cto.com/zhaohaibo/1284602

    總結

    以上是生活随笔為你收集整理的【Spring学习笔记】之【3.3 DI的深入 二】的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 青青久久国产 | 色婷婷综合久久久久中文 | 天天干天天操天天玩 | 欧美精品一线 | 亚洲欧洲精品视频 | av在线播放不卡 | 成年人在线观看av | 亚洲成人网在线观看 | 天天操天天爽天天干 | 在线观看福利视频 | 日本一区二区高清不卡 | 日本在线观看a | wwwxxx日本人| 夜操操| 色婷婷婷婷 | 丰满少妇乱子伦精品看片 | 亚洲一区视频网站 | 一级视频在线免费观看 | 杂技xxx裸体xxxx欧美 | 精品国产精品三级精品av网址 | 国产夫妻自拍av | 秘密基地动漫在线观看免费 | 成人午夜免费毛片 | 精品久久久久久久久久久aⅴ | 青青草原免费观看 | 婷婷五月小说 | 色噜噜一区二区三区 | 伊人天天| 免费无码毛片一区二三区 | 蜜臀一区二区三区 | 有码中文 | 40一50一60老女人毛片 | av片在线观看免费 | 艳妇臀荡乳欲伦交换电影 | 五月天导航 | 成人精品综合 | 亚洲精品中文字幕在线 | 欧美黄色大片免费看 | 日韩一区二区三区在线看 | 最近中文字幕免费视频 | 欧美片网站免费 | 精品亚洲aⅴ无码一区二区三区 | 一本一道久久综合狠狠老精东影业 | 五月婷婷激情在线 | a级片久久 | 无码精品人妻一区二区 | 久操视频在线播放 | 男女涩涩| 中文字幕人妻一区二区三区视频 | 精品无码人妻一区二区三区品 | 日本www| 暖暖av | 亚洲经典一区 | 国产在线播放网站 | 久久电影一区二区 | 午夜精品一区二区三区在线播放 | 日本成人一二三区 | 国产精品不卡在线观看 | 日日夜夜噜噜噜 | 激情av在线| 国产高清自拍av | 黄a在线观看 | 一区二区国产在线 | av少妇在线 | 天堂√8在线中文 | 久久久久久久偷拍 | www.蜜臀 | 日韩黄色网页 | 伦理亚洲 | 秋霞福利视频 | 亚洲无av | 国产精品自拍99 | 国内精品视频在线观看 | 蜜桃av噜噜一区二区三区麻豆 | 中国亚洲女人69内射少妇 | a成人在线 | 成人做爰免费视频免费看 | 最新激情网 | 人妻少妇偷人精品久久久任期 | 伊人色在线视频 | 成人影音在线 | 曰女同女同中文字幕 | 水蜜桃久久 | 亚洲精品99999 | 日本精品一区二区三区视频 | 精品一区二区三区蜜臀 | 美女扒开内裤让男人捅 | 日本边添边摸边做边爱 | 揄拍成人国产精品视频 | 久久精品在线观看 | 深夜福利麻豆 | 亚洲视频精品 | 国产精品资源在线观看 | 中文字幕一区电影 | 亚洲天堂岛 | 亚洲精品成人在线视频 | 人妖性生活视频 | 欧美123区 | 日本v片|