詳細解析@Resource和@Autowired的區別 , 以及@Qualifier的作用
首先 .
@Resource是javax.annotation 包中的註解類 , 是jdk中封裝的 .
@AutoWired是spring的中註解,依賴於spring上下文.
相同點:
@Resource 和 @Autowired 都可以用在類中的field 或者function 上 , 在類初始化的時候 , 自動為field 賦值 , 自動為function注入引數並且執行該方法(不僅僅侷限於set方法) .
不同點:
1. @Autowired 寫在建構函式上,為構造器注入引數 , @Resource不能建構函式上.
2. @Autowired是根據注入類的型別來尋找bean的 , 如果同一個Type的類注入了多個id(或者name) 不一樣的bean , 那麼用@Autowired就無法準確的找到是哪個bean了, 這個時候就會丟擲一個異常. 如果放在建構函式上 , 那麼spring預設會使用該帶參的構造器初始化類 , 當autowired傳入required=false 時 , 如果初始化時沒有找到注入的bean , 且該bean仍然有寫空參的建構函式 , 則spring會自動呼叫空參的建構函式初始化 , 但是如果沒有寫空參建構函式 , 在會丟擲異常.
3. @Resource分兩種情況 :
- 在不傳引數或者傳入空參的情況下 , @Resource預設根據注入bean的欄位名來尋找bean (若放在function上 , 如果該function為set方法, 則bean名稱解析為set對應的欄位名 , 如果不是set方法 , 則bean解析為function的方法名) , 如果找不到 , 在根據型別來尋找對應的bean, 如果還找不到 , 丟擲異常 , 如果找不到與欄位名相匹配的bean , 但是型別匹配的卻有多個 , 也丟擲異常 ;
- 在傳入確定引數的情況下 , @Resouce或根據傳入的name值來尋找這個名稱的bean , 如果找不到則丟擲異常 , 或者根據type值來尋找這個型別的bean , 也可以同時指定name和type.
@Qualifier 可以寫在field 或者function傳入引數的引數型別前面 , 用來指定注入bean的名稱 ,如果不指定value, 那麼預設是空名稱, 也是可以編譯通過的 , 但是無法匹配到對應的bean (以兩個同一interface的實現注入不同名稱的bean來測試 , 如果本身只有一個對應的bean , 或者僅僅通過@Resource 或 @Autowired就可以找到對應的bean , 就無法測試出來@Qualifier的效果了 ) ,所以一般情況下 , 使用@Qualifier都需要傳入value引數 , 指定bean的名稱 ,
最後注意一點 , @Resource雖然是JDK中的註解類 , 但是jdk中並沒有具體的處理方式 , 需要依賴於其他框架或者工具才能實現具體功能 , 如果不載入spring容器 , 單獨使用@Resource註解 , 是沒有任何作用的.
下面是測試用的程式碼 , 很簡單的例子 , 感興趣的朋友 , 可以自己改一改userService來測試一下各種情況 .
beans:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.pindao.six" />
</beans>
interface
public interface UserDao {
}
實現:
@Component("userDao")
public class UserDaoImpl implements UserDao {
private int daoId = 1;
@Override
public String toString() {
return "UserDaoImpl{" +
"daoId=" + daoId +
'}';
}
}
@Component("userDao2")
public class UserDaoImpl2 implements UserDao {
private int daoId = 2;
@Override
public String toString() {
return "UserDaoImpl{" +
"daoId=" + daoId +
'}';
}
}
service
@Component
public class UserService {
private UserDao userDao;
public UserService(){
System.out.println("this is constructor");
}
// @Autowired(required = false)
public UserService(UserDao userDao){
System.out.println("this is constructor with paramater");
this.userDao = userDao;
}
public void getDao(){
System.out.println(this);
System.out.println(userDao);
}
public UserDao getUserDao() {
return userDao;
}
@Autowired
public void setUserDao(@Qualifier("userDao2") UserDao userDao) {
this.userDao = userDao;
}
public void userDao2(UserDao userDao){
System.out.println("this is normal mothed");
this.userDao = userDao;
}
}
jUnit測試:
public class UserServiceTest {
@Test
public void testGetDao() throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
System.out.println("----");
UserService userService = (UserService)context.getBean("userService");
userService.getDao();
}
}