Autowired和Resource的區別和聯絡
聯絡
@Autowired和@Resource註解都是作為bean物件注入的時候使用的
兩者都可以宣告在欄位和setter方法上
注意:如果宣告在欄位上,那麼就不需要再寫setter方法。但是本質上,該物件還是作為set方法的實參,通過執行set方法注入,只是省略了setter方法罷了
區別
@Autowired註解是Spring提供的,而@Resource註解是J2EE本身提供的
@Autowird註解預設通過byType方式注入,而@Resource註解預設通過byName方式注入
@Autowired註解注入的物件需要在IOC容器中存在,否則需要加上屬性required=false,表示忽略當前要注入的bean,如果有直接注入,沒有跳過,不會報錯
對於byName和byType方式不太熟悉的可以看一下這裡:Spring中的byName與byType
簡單來說,byName就是變數名去匹配bean的id屬性,而byType則是變數型別去匹配bean的class屬性
<bean id="userService" class="com.test.UserServiceImpl">
</bean>
@Autowired
private UserService userService;
此處byName就是拿變數名userService去匹配IOC容器的iduserService,匹配成功;而byType就是拿變數型別UserService去匹配IOC容器的idcom.test.UserService.UserServiceImpl,因為UserServiceImpl是UserService實現,所以也匹配成功
接下來再分別講講@Autowired註解和@Resource註解的使用
@Autowird註解的使用
步驟:@Autowird預設的注入方式為byType,也就是根據型別匹配,當有多個實現時,則通過byName注入,也可以通過配合@Qualifier註解來顯式指定name值,指明要使用哪個具體的實現類
舉例:
首先有一個介面UserService和兩個實現類UserServiceImpl1和UserServiceImpl2,並且這兩個實現類已經加入到Spring的IOC容器中了
@Service
public class UserServiceImpl1 implements UserService
@Service
public class UserServiceImpl2 implements UserService
通過@Autowired注入使用
@Autowired
private UserService userService;
根據上面的步驟,可以很容易判斷出,直接這麼使用是會報錯的
原因:首先通過byType注入,判斷UserService型別有兩個實現,無法確定具體是哪一個,於是通過byName方式,這裡的變數名userService也無法匹配IOC容器中id(此處指的userServiceImpl1和userServiceImpl2),於是報錯。
注意:通過註解注入到IOC容器的id值預設是其類名首字母小寫
解決方案
方式一:
// 方式一:改變變數名
@Autowired
private UserService userServiceImpl1;
方式二:
// 方式二:配合@Qualifier註解來顯式指定name值
@Autowired
@Qualifier(value = "userServiceImpl1")
private UserService userService;
@Resource註解的使用
步驟:@Resource預設通過byName注入,如果沒有匹配則通過byType注入
舉例:
@Service
public class UserServiceImpl1 implements UserService
@Service
public class UserServiceImpl2 implements UserService
@Resource
private UserService userService;
首先通過byName匹配,變數名userService無法匹配IOC容器中任何一個id(這裡指的userServiceImpl1和userServiceImpl2),於是通過byType匹配,發現型別UserService的實現類有兩個,仍然無法確定,於是報錯。
同時@Resource還有兩個重要的屬性:name和type,用來顯式指定byName和byType方式注入
使用:對應4種情況
// 1. 預設方式:byName
@Resource
private UserService userDao;
// 2. 指定byName
@Resource(name="userService")
private UserService userService;
// 3. 指定byType
@Resource(type=UserService.class)
private UserService userService;
// 4. 指定byName和byType
@Resource(name="userService",type=UserService.class)
private UserService userService;
既沒指定name屬性,也沒指定type屬性:預設通過byName方式注入,如果byName匹配失敗,則使用byType方式注入(也就是上面的那個例子)
指定name屬性:通過byName方式注入,把變數名和IOC容器中的id去匹配,匹配失敗則報錯
指定type屬性:通過byType方式注入,在IOC容器中匹配對應的型別,如果匹配不到或者匹配到多個則報錯
同時指定name屬性和type屬性:在IOC容器中匹配,名字和型別同時匹配則成功,否則失敗