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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

@Resource详解-代码示例

發布時間:2023/12/16 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 @Resource详解-代码示例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

@Resource注解詳解

      • 屬性介紹
      • @Resource 的裝配規則
      • 靈魂總結
        • 先來看下@Resource的應用場景
      • 代碼演示
        • 默認情況
          • 裝配代碼
          • 運行測試
          • 分析
        • byName (name默認屬性名)
          • 裝配代碼
          • 運行測試
          • 分析
        • byName (name顯示指定)
          • 裝配代碼
          • 運行測試
          • 分析
        • byType 顯示指定
          • 裝配代碼
          • 運行測試
          • 分析
      • finally

此注解來源于JSR規范(Java Specification Requests),其作用是找到依賴的組件注入到應用來,它利用了JNDI(Java Naming and Directory Interface Java命名目錄接口 J2EE規范之一)技術查找所需的資源。

網上查了些資料看的有點暈暈, 這里用例子來說明 @Resource的用法 , 以及需要注意的問題

屬性介紹

name:資源的JNDI名稱。在spring的注入時,指定bean的唯一標識。 type:指定bean的類型。 lookup:引用指向的資源的名稱。它可以使用全局JNDI名稱鏈接到任何兼容的資源。 authenticationType:指定資源的身份驗證類型。它只能為任何受支持類型的連接工廠的資源指定此選項,而不能為其他類型的資源指定此選項。 shareable:指定此資源是否可以在此組件和其他組件之間共享。 mappedName:指定資源的映射名稱。 description:指定資源的描述。

@Resource 的裝配規則

默認情況下,即所有屬性都不指定,它默認按照byType的方式裝配bean對象。
如果指定了name,沒有指定type,則采用byName。
如果沒有指定name,而是指定了type,則按照byType裝配bean對象。
當byName和byType都指定了,兩個都會校驗,如果找不到,或者找到多個(比如byName的方式找到了BeanA, ByType的方式找到了BeanB ) 這種情況也是不會成功的.

上述略顯官方的味道的解釋,相信不少人也是暈暈的 , 也對這個"默認值" 情況解釋的不到位 , 下面來個靈魂總結.

靈魂總結

注意: !!! type和name的根本邏輯就是 type是劃定一個范圍 , 然后name 在其中選擇一個
舉個栗子:

  • 如果 type 只匹配了 一個 ( 1 ) , 那么成功裝備結果 必然是 1 , 如果name只有找到了1 , 或者沒有找到的情況下才會配置成功( 沒有顯示指定name值, 默認為變量名) , name如果在容器中找到了非1 的bean ,則會報類型錯誤.
  • 如果type 匹配了 ( 1 , 2 , 3 ) 多個實例 , 那么name只有匹配到 其中一個,才會裝配成功, 如果一個也匹配不到 , 則會報錯 ,因為spring不知道到底要裝配哪個實例.
  • 如果type一個都沒有匹配到,那就直接涼涼了 ,報錯:No qualifying bean of type xxx 的錯誤, 即使name指定的值在容器中找到了符合條件的bean實例, 也會報 類型不符合的錯誤.

先來看下@Resource的應用場景

@Resource的應用場景一般都是在裝配的時候出現了多個符合條件的bean , 這時候用@Autowired注解自動裝配就會出現了問題 . 此時就可以用@Resource注解類解決問題 . (@Qualifier + @Autowired 也可以實現, 這里主要說下@Resource注解) , 通常就是解決多態的問題.

代碼演示

這里示例將@Resource 放在了類的屬性上

首先有個HelloService接口:

package com.resource.service; public interface HelloService {void sayHello(); }

兩個實現類 , HelloServiceImpl1 和 HelloServiceImpl2 , 實現的sayHello()方法,分別在控制臺打印出 hello one! , hello two! 如下:

package com.resource.service.impl; @Component public class HelloServiceImpl1 implements HelloService {public void sayHello() {System.out.println("hello one!");} } package com.resource.service.impl; @Component public class HelloServiceImpl2 implements HelloService {public void sayHello() {System.out.println("hello two!");} }

業務類UseService 實現屬性裝配

package com.resource; @Component public class UseService {//@Qualifier("helloServiceImpl1")//@Autowired//private HelloService helloService;@Resourceprivate HelloService helloServiceImpl;public void say(){helloServiceImpl.sayHello();} }

測試類

public static void main(String[] args) {//1.創建容器AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext("com");//2.獲取對象UseService useService = ac.getBean("useService", UseService.class);useService.say();}

默認情況

裝配代碼

其它代碼不變

@Resourceprivate HelloService helloServiceImpl;public void say(){helloServiceImpl.sayHello();}
運行測試

這時候如果什么都不指定, 運行則會報錯如下:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException : No qualifying bean of type 'com.resource.service.HelloService' available : expected single matching bean but found 2: helloServiceImpl1,helloServiceImpl2
分析

@Resource是用 ByType和ByName 來裝配的, 如果沒有顯示的通過type屬性和name屬性指定 , “就會找其默認值”
在這個示例中type就是HelloService.class , 又因為其是接口, spring在容器中找到了其兩個已經注入容器的實現類分別為 helloServiceImpl1 , helloServiceImpl2 這兩個實例. (范圍)
而name 也沒有通過屬性執行 , name默認值就是變量的名稱 helloServiceImpl , 顯然spring容器中是沒有的. (后續會通過測試驗證)
通過默認指定值得ByType和ByName 其結果就是得到了兩個符合要求的實例 , 而name也沒有完成在type后有多個實例的情況下 “選一個” . 所有會有上述的把報錯信息.

byName (name默認屬性名)

裝配代碼

其它代碼不變

@Resourceprivate HelloService helloServiceImpl1;public void say(){helloServiceImpl1.sayHello();}

這個變化就是上個示例中將屬性名從helloServiceImpl 改成了 helloServiceImpl1 .

運行測試
hello one! Process finished with exit code 0
分析

這里同樣byType后 有兩個實例 helloServiceImpl1 , helloServiceImpl2 , 而name沒有顯示指定, 默認為變量名 helloServiceImpl1 , 也完成了選一個的任務, 進而裝配成功!

byName (name顯示指定)

裝配代碼

其它代碼不變

@Resource(name="helloServiceImpl2")private HelloService helloServiceImpl1;public void say(){helloServiceImpl1.sayHello();}

這個變化就是上個示例中 指定了name屬性的值

運行測試
hello two! Process finished with exit code 0
分析

可以看到屬性名為helloServiceImpl1 , 顯示指定的是helloServiceImpl2 , 即如果顯示指定name的值得話就取該值, 相當于是對默認的變量名覆蓋了(可以這樣理解). 就是有顯示指定就用顯示指定的, 沒有就用變量名. 結果輸出hello two! 就是對的了.

byType 顯示指定

裝配代碼

其它代碼不變 , 裝配改為顯示指定type值,如下

@Resource(type = HelloServiceImpl1.class )private HelloService helloServiceImpl1;public void say(){helloServiceImpl1.sayHello();}

這個變化就是上個示例中 指定了name屬性的值

運行測試
hello one! Process finished with exit code 0
分析

顯示指定了type = HelloServiceImpl1.class , 也就范圍就是 helloServiceImpl1 , 根據開頭的靈魂總結 , type已經確定了一個 , 那么 name (默認變量名 或者顯示指定 ) 的值 就必須是helloServiceImpl1 或者是一個在spring容器中找不到的名稱.
注意: 這是個坑, 如果你指定的變量名剛好是spring容器中的某個bean的id , 那么這里就會報
Bean named ‘xxxx’ is expected to be of type ‘com.resource.service.impl.HelloServiceImpl1’ 的異常!!!
這里用代碼演示下:
新建了個HiService類

package com.resource.service.impl; @Component public class HiService {public void sayHello() {System.out.println("Hi Hi!");} }

裝配類 (主要改了變量名為hiservice ,HiService 的bean id)

@Resource(type = HelloServiceImpl1.class )private HelloService hiService;public void say(){hiService.sayHello();}

運行報類型的錯誤如下:

org.springframework.beans.factory.BeanNotOfRequiredTypeException:Bean named 'hiService' is expected to be of type 'com.resource.service.impl.HelloServiceImpl1' but was actually of type 'com.resource.service.impl.HiService'

finally

以上僅為個人見解 , 能看到這里希望能讓您有所收獲.
拋磚引玉 , 如有不到之處, 敬請指正.

總結

以上是生活随笔為你收集整理的@Resource详解-代码示例的全部內容,希望文章能夠幫你解決所遇到的問題。

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