深入分析@Resource和@Autowired註解區別
引言
@Resource和@Autowired都是Spring Framework中用於依賴註入的註解,但它們有幾點不同:
來源不同:@Resource註解來自於J2EE規范中;而@Autowired註解是Spring框架提供的。
搜索策略不同:@Resource註解默認按照名稱進行匹配查找,如果找不到,則按照類型進行匹配。而@Autowired註解默認是按照類型進行匹配,如果出現多個類型一致的實例對象,則需要指定名稱。
屬性不同:@Resource註解沒有屬性名稱,隻有一個name屬性,表示要註入的Bean名稱。而@Autowired註解有兩個重要屬性:required和name,其中required屬性表示是否必須註入該屬性,默認為true;name屬性表示要註入的Bean名稱。
1、用法層面分析
首先,我們創建一個接口UserService
和兩個實現類UserServiceImpl1
和UserServiceImpl2
。
public interface UserService { void save(); } @Service public class UserServiceImpl1 implements UserService { @Override public void save() { System.out.println("UserServiceImpl1 save"); } } @Service public class UserServiceImpl2 implements UserService { @Override public void save() { System.out.println("UserServiceImpl2 save"); } }
然後,我們可以在需要使用UserService
的地方進行依賴註入。
使用@Resource註解:
@Component public class UserController { @Resource private UserService userService; // ... }
使用@Autowired註解:
@Component public class UserController { @Autowired(required = false) @Qualifier("userServiceImpl1") private UserService userService; // ... }
上面的代碼中,@Resource
註解直接將UserService
對象註入到userService
屬性中,而@Autowired
註解需要結合@Qualifier
註解來指定具體的Bean名稱,並且通過required
屬性設置是否必須註入該屬性。註意,@Autowired
註解也可以省略@Qualifier
註解,此時會按照類型進行匹配查找對應的Bean。
2、概念層面分析
再來分析一下其中的道道~~
Spring Framework中的依賴註入實現原理是基於Java反射機制和JavaBean規范的。
- 通過反射機制實例化對象
Spring框架通過反射機制實例化需要註入的Bean對象,並將其存儲到一個Map中,其中Key為Bean名稱,Value為Bean實例對象。
- 通過JavaBean規范完成Bean屬性註入
接下來,Spring會根據JavaBean規范(即屬性名以及該屬性的setter方法)查找需要註入的屬性,並通過反射機制調用對應的setter方法進行屬性註入。
- 依賴註入的搜索策略
在依賴註入的過程中,Spring框架通常采用兩種搜索策略:
- 按照類型搜索:當需要註入的屬性的類型與容器中的多個Bean的類型一致時,會根據不同的註解選擇不同的搜索策略。比如使用@Autowired註解時,默認按照類型匹配查找對應的Bean。
- 按照名稱搜索:當需要註入的屬性的類型不唯一,或者需要註入的Bean名稱與屬性名稱不一致時,可以使用@Qualifier註解指定要註入的Bean名稱。
- 使用各種註解進行依賴註入
Spring框架提供瞭多種註解用於依賴註入,包括:
- @Autowired:按照類型進行註入;
- @Resource:按照名稱進行註入;
- @Value:註入簡單類型或字符串類型的屬性;
- @Inject:JSR-330標準定義的註解,功能與@Autowired類似。
Spring Framework的依賴註入實現原理是基於Java反射機制和JavaBean規范的,並通過多種註解實現不同的依賴註入方式。
@Resource和@Autowired都是Spring的依賴註入註解,但它們有如下區別:
-
來源不同:@Resource是Java EE規范定義的註解,而@Autowired是Spring提供的註解。
-
屬性不同:@Resource註解沒有required屬性,隻有name屬性,表示要註入的Bean名稱;而@Autowired註解有required和name屬性,其中required表示是否必須註入該屬性,默認為true;name表示要註入的Bean名稱。
-
查找方式不同:@Resource註解默認是根據byName的方式進行查找,如果找不到則按照byType進行查找;而@Autowired默認是根據byType方式進行查找。
-
兼容性不同:@Resource註解可以與JSR-330的@Inject註解搭配使用;而@Autowired註解隻能與Spring組件一起使用。
-
應用場景不同:@Resource註解主要應用於Java EE環境,而@Autowired註解則是在Spring框架中使用最廣泛的依賴註入註解之一,可以適用於不同的應用場景。
下面分別介紹@Resource和@Autowired註解的優缺點:
@Resource優點:
-
簡單易用,在類中使用非常方便。
-
可以和@Inject註解一起使用。
-
支持指定Bean名稱,可以更精確地進行依賴註入。
@Resource缺點:
-
Spring框架對@Resource註解的支持不如@Autowired豐富。
-
僅支持byName和byType兩種註入方式,比@Autowired的支持更為有限。
@Autowired優點:
-
支持復雜的依賴註入配置,可以通過多種方式進行依賴註入。
-
Spring框架對@Autowired註解的支持非常豐富,是Spring中使用最廣泛的註解之一。
-
可以指定是否必須註入該屬性,也可以指定Bean名稱進行註入。
-
除瞭在類中使用之外,還可以在構造方法、Setter方法及任何標記瞭@Bean的方法中使用@Autowired註解。
@Autowired缺點:
-
配置較為繁瑣,需要指定required和name屬性等。
-
需要遵循Spring的自動掃描機制,隻有標記瞭@Component、@Service、@Controller和@Repository等註解的類才會被Spring容器進行管理。
對於依賴註入的原理,可以簡單地概括為以下三個步驟:
-
在應用程序啟動時,Spring容器負責創建和管理所有的Bean實例對象。
-
在需要使用某個Bean的時候,Spring容器會通過反射機制將該Bean註入到需要使用的類或對象中。
-
在Bean註入的過程中,Spring容器會根據不同的註解(如@Resource、@Autowired)采用不同的依賴註入方式,完成依賴註入的過程。
@Resouce和@Autowired都是Spring提供的依賴註入註解,各有優缺點。在實際開發中,可以根據具體的應用場景選擇合適的註解進行使用。
3、源碼層面分析
在Spring Framework源碼層面,@Resource和@Autowired註解的實現類分別為javax.annotation.Resource和org.springframework.beans.factory.annotation.Autowired。下面我們來看一下它們的具體實現。
@Resource註解的實現原理:
- 如果@Resource註解的name屬性不為空,則Spring容器根據該屬性值查找需要註入的Bean實例對象;如果name屬性為空,則默認使用字段名作為Bean名稱進行查找。
- Spring容器會先根據byName註入方式進行查找,如果沒有找到對應的Bean實例,則根據byType方式進行查找。
- 如果找到瞭對應的Bean實例,則使用反射機制將該Bean實例註入到需要使用該實例的類或對象中。
- 如果沒有找到對應的Bean實例,則拋出NoSuchBeanDefinitionException異常。
代碼示例:
@Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Resource { String name() default ""; Class<?> type() default java.lang.Object.class; boolean shareable() default true; }
@Autowired註解的實現原理:
- Spring容器會根據AutowiredAnnotationBeanPostProcessor類和AutowiredAnnotationBeanPostProcessor類的派生類進行處理,將使用@Autowired註解標記的所有屬性註入到需要使用的類或對象中。
- 對於AutowiredAnnotationBeanPostProcessor,其實現瞭BeanPostProcessor接口,在Bean實例化、初始化的過程中會攔截@Autowired註解。
- 當Spring容器遇到@Autowired註解時,會自動調用AutowiredAnnotationBeanPostProcessor類的postProcessPropertyValues方法,該方法會根據不同的註解屬性值進行不同的依賴註入處理。
- 在處理@Autowired註解時,Spring容器默認使用byType的方式進行查找,如果存在多個匹配類型的Bean,則根據類名進行匹配;如果仍然無法確定註入哪個Bean,則拋出NoSuchBeanDefinitionException異常。
代碼示例:
@Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Autowired { boolean required() default true; String value() default ""; }
無論是@Resource註解還是@Autowired註解,在Spring Framework源碼實現上都是通過反射機制和BeanPostProcessor接口完成依賴註入的。在實際開發中,我們可以研究對應的源碼實現,深入瞭解它們的原理,從而更好地使用這些依賴註入註解。
以上就是深入分析@Resource和@Autowired註解區別的詳細內容,更多關於@Resource @Autowired註解區別的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- 淺談spring DI 依賴註入方式和區別
- Spring中@Autowired與@Resource的區別詳析
- 一文搞懂Spring中@Autowired和@Resource的區別
- 關於@Autowierd && @Resource 你真的瞭解嗎
- Spring的@Autowired加到接口上但獲取的是實現類的問題