Resource使用起來到底有什么區別?
感謝邀請!
1、首先我們看下 @Autowired 和 @Resource 的用法
@Autowired 的用法@Autowired 是Spring自帶的注解,位于 包
org.springframework.beans.factory.annotation
下1、自動注入
1、自動裝配可以按照類型進行裝配,如果在IOC容器發現多個相同類型的組件怎么辦呢?
我們可以按照屬性名稱來進行裝配,比如存在UserDao1 和 UserDao2
@Autowired
private UserDao userDao;
我們通過@Autowied 修飾 屬性名稱時 userDao, 那么 先用byType來查找,如果IOC容器中存在多個相同類型的組件,則使用userDao名稱來找,若屬性名稱為userDao2,那么就加載userDao2的組件。
2、如果我們需要需要指定特定的組件來進行裝配呢?又該怎么辦呢?
可以使用@Qualifier("userDao") 來指定裝配的組件 或者 在配置類的@Bean上加上
@Primary注解。
@Autowired
@Qualifier("userDao")
private UserDao userDao2;
3、如果我們加載的時候既沒有userDao有沒有userDao2,那么裝配的時候是什么現象呢?
配置如下:
上圖初始化了兩個UserDao, Bean組件名稱為 userDao3 和 userDao2。
再次注入的 時候:
先按byType去查找,查找的時候發現有兩個UserDao類型,從而又轉換用userDao名稱查找。但是又查不到,所以 報一下錯誤。
No qualifying bean of type 'com.wy.study.autowired.UserDao' available:
expected single matching bean but found 2: userDao3,userDao2
上述的錯誤是,期望去獲取一個實例,但是卻找到了兩個。
如果不想拋出異常呢,我們需要指定required 為false的時候就可以了
@Autowired(required = false)
private UserDao userDao;
但是上述只能保證 啟動的時候不報錯,但是調用的時候還是得報錯。
4、@Autowired 也可以使用在方法參數上
4、@Autowired 標注在構造方法上
@Resource 注解@Resource 是由J2EE 體用的,需要導入包 javax.annotation.Resource。
功能和@Autowired 的功能差不多一樣,但是不支持@Primary 和 @Qualifier的支持
@Resource 有兩個屬性: name 和 type
name: bean的名稱 type: bean的類型
默認按照 byName自動注入
有下面4中情況
① 如果只是指定了name屬性,則從IOC容器中查找名稱為userDao的bean進行裝配,找不到則拋出 異常。
@Resource(name = "userDao")
private UserDao userDao;
② 如果指定了type,則從IOC容器中查找UserDao類型的Bean,找不到或者找到多個,都會拋出異常。
③ 如果既沒指定name,又沒指定type,則回退為一個原始類型進行匹配,如果匹配則自動裝配;
④ 若兩個屬性都使用了,則需要找到唯一匹配的bean進行裝配,找不到則拋出異常。
@Autowired 注解 在Spring源碼中的解析容器對Bean的自動裝配發生在容器對Bean依賴注入的過程中,在對Spring IOC 容器的以阿里注入源碼分析,我們已經 知道容器對bean實例對象的依賴屬性注入發生在
AbstractAutowireCapableBeanFactory 類的 populateBean 方法。下面我們對其的解析 進行說明。
1、AbstractAutowireCapableBeanFactory 對Bean實例對象進行屬性依賴注入
當應用程序第一次getBean() 方法時,向IOC容器索取Bean時,容器創建實例對象,并且對Bean實例對象進行屬性依賴注入,AbstractAutowireCapableBeanFactory 的populateBean 方法對屬性進行依賴注入
調用棧如下:
源碼解釋如下:
2、Spring IOC 容器根據Bean名稱或者類型進行autowired 自動屬性依賴注入
Spring IOC容器根據Bean名稱或者類型進行autowired自動屬性依賴注入的代碼如下:
從上面可以看到,通過屬性名進行自動依賴注入相比通過屬性類型進行自動依賴注入要稍微簡單一些,但是真正實現屬性注入的是 DefaultSingletonBeanRegistry 類的registerDependentBean方法進行注入;
解析步驟如下:
處理bean名稱,將別名轉換為規范的Bean名稱
String canonicalName = canonicalName(beanName);
下面是多線程同步,保證容器內的數據的一致性
在容器中通過"Bean名稱找到全部依賴Bean名稱集合“查找指定名稱Bean的依賴Bean
synchronized (this.dependentBeanMap)
(1) 獲取指定 名稱Bean的所有依賴Bean名稱
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
如果 dependentBeanMap 中么有,則把依賴的bean放進去
(2) 將bean所依賴的Bean添加到容器的集合中
dependentBeans.add(dependentBeanName);
可以看出,autowired 的實現過程如下:
① 對Bean的屬性調用getBean方法,完成依賴Bean的初始化和依賴注入
② 將依賴Bean的屬性引用設置到被依賴的Bean屬性上
③ 將依賴Bean的名稱和被依賴Bean的 名稱存儲到IOC容器上
總結1、@Resource和@Autowired都可以用來裝配bean,都可以寫在字段上或者是寫在setter方法上。
2、@Autowired 默認是按照byType進行裝配的,所以默認情況下依賴的對象必須存在,如果允許為null,則可以使用required屬性為false,如果想使用byName進行裝配,那么可以和@Qualifier注解相互配合。
3、@Resource默認是按照byName進行裝配的,如果指定了name,則會查找id指定name的bean進行裝配,如果指定了type,則會從Spring IOC 中 找到唯一的Bean進行裝配,找不到則排除異常。
推薦使用@Resource注解在字段上,這樣就不用寫setter方法了,并且這個注解屬于J2EE的,減少了與Spring的耦合。
本文由碼農的一天撰寫,如果你認同我的觀點的話,可以點贊加關注一下;如果你對本篇文章有其他見解的話,也歡迎在下方的評論區瀏覽討論!