1、實踐出真知
@Resource 是 JSR-250 規範的一部分
說到 @Resource 大家肯定會想到 @Autowired, 至於兩者的區別, 大部門分童鞋都知道。
@Resource 的作用和 @Autowired 一樣,只不過 @Autowired 是按 byType 自動注入,而 @Resource 默認按 byName 自動注入,而且還提供了 name 和 type 兩個屬性,其含義也容易理解,分別按 byName 和 byType 注入。
如果兩個屬性都沒有提供的話,則根據屬性名稱注入,我理解的是 byName,還有地方說是通過反射機制使用 byName自動注入。
俗話說的好 no tu no bb,接下來多圖慎入。下圖爲測試項目的結構。
(1)@Autowired,匹配多個實現類,但默認屬性名匹配不上,報錯
我們先來看看 @Autowired 的測試情況。
我通過在 SpringTest 類的 Main 方法中,初始化和啓動 Spring 容器。配置中配置了兩個 MyTestService 接口的實現類 MyTestServiceImpl2 和 MyTestServiceImpl3,打印了簡單的一句話。結果肯定顯而易見,報錯了。
我在 註解@Service 中配置了兩個實現類,默認按 byType 注入,發現多個,根據 byName注入,無法找到 name 爲 myTestService 的 bean,所以報錯了,接下來修改屬性名,再看。
(2)@Autowired,匹配多個實現類,默認屬性名匹配上其中一個,正常
這次同樣的步驟,默認按 byType 注入,發現多個,根據 byName 注入,找到 name 爲 myTestServiceImpl2 的 Bean。成功執行。
(3)@Resource 沒指定name屬性,且默認屬性名匹配不上,但只匹配上一個實現類,正常
來看看 @Resource 的情況,請看下圖配置,我註釋掉了 MyTestServiceImpl2 實現類的聲明。
注意 HomeController 中聲明的屬性 myTestService,在配置中沒有這個屬性對應的 Bean,@Resource 沒有配置 name 和 type 的情況下,結果是什麼呢?現在大家猜一下執行成功還是失敗。
是的,沒有報錯,你猜對了嗎?那好現在我們把 HomeController 中的屬性名稱再改一下。
(4)@Resource 沒指定name屬性,但默認屬性名匹配,正常
我把屬性改爲存在的 Bean,myTestServiceImpl3,然後我們再來看看結果,毫無疑問結果肯定是沒有報錯。
那好,按照以上測試結果來看,當 @Resource 沒有提供 name 和 type 屬性的時候,如果 byName 沒有找到對應的 Bean 時,則會根據依賴屬性的類型去 Spring 容器中查找是否有提供了其他類型相同的 Bean,如果有則自動注入,如果沒有則報錯。當然如果根據 byName 找到了則直接注入。接下來,我們再來看看,name 和 type 的情況。
(5)@Resource 指定name屬性,但屬性名不匹配,報錯
我在 HomeController 中添加了 @Resource 的 name 屬性 爲 myTestServiceImpl2,那麼現在如果執行,結果是否會報錯?
是的報錯了,因爲註釋了 myTestServiceImpl2 的聲明,所以在使用 name 屬性查找時,無法找到對應的 Bean,所以直接報錯,沒有再次去通過類型到 Spring 容器中查找。接下來我們再看看使用配置的 Bean的情況。
(6)@Resource 指定name屬性,屬性名匹配,正常
我使用了 userDaoImpl1 這個 Bean,那結果顯而易見,肯定沒有問題。
type 屬性我就不用演示了吧,和 name 屬性是一樣,如果同時提供了 name 和 type 的話,那就必須兩個都要匹配才能注入依賴,否則就會注入失敗。總算把 @Resource 註解搞明白了,之前一直以爲 @Resource 註解就是默認 byName 裝配,不知道里面還有這麼多彎彎繞呢。
2、@Autowired
@Autowired默認byType自動注入,如果實例結果不唯一,那麼將會拋出異常
@Autowired可與@Qualifier("beanName")搭配使用,注入指定bean。
@Autowired
@Qualifier("baseDao")
private BaseDao baseDao;
如,同一個接口,兩個實現類,就可以使用該方式指定注入。
@Autowired(required=false)
表示如果spring上下文中沒有找到該類型的bean ,將會使用
new SoftPMServiceImpl();
private ISoftPMService softPMService = new SoftPMServiceImpl();
3、@Resource
@Resource默認按byName自動注入
但是@Resource有兩個屬性是比較重要的,分別是name和type;
如果使用name屬性,則使用byName的自動注入策略; .
而使用type屬性時則使用byType自動注入策略;
@Resource裝配順序
1. 如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常
2. 如果指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常
3. 如果指定了type,則從上下文中找到類型匹配的唯一bean進行裝配,找不到或者找到多個,都會拋出異常
4. 如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有匹配,則回退爲一個原始類型進行匹配,如果匹配則自動裝配;
使用方式如下:
//@Resource(name="dataSource");
@Resource(type="DataSource.class");
@Resource
private DataSource dataSource;
//inject the bean named 'dataSource';
4、簡要對比表格
註解對比 | @Resource |
@Autowire |
---|---|---|
註解來源 | JDK | Spring |
裝配方式 | 優先按名稱 | 優先按類型 |
屬性 | name、type | required |
參考: