轉:@Resource與@Autowired用法區別

原文鏈接:https://blog.csdn.net/magi1201/article/details/82590106

原文鏈接:https://blog.csdn.net/magi1201/article/details/82590106

spring中,@Resource和@Autowired都是做bean的注入時使用。使用過程中,有時候@Resource 和 @Autowired可以替換使用;有時,則不可以

    下面,根據自己的學習,整理下這兩個註解使用中的共同點和不同點,及用法上的不同。

    共同點:

     @Resource和@Autowired都可以作爲注入屬性的修飾,在接口僅有單一實現類時,兩個註解的修飾效果相同,可以互相替換,不影響使用。

    不同點:

  • @Resource是Java自己的註解,@Resource有兩個屬性是比較重要的,分是name和type;Spring將@Resource註解的name屬性解析爲bean的名字,而type屬性則解析爲bean的類型。所以如果使用name屬性,則使用byName的自動注入策略,而使用type屬性時則使用byType自動注入策略。如果既不指定name也不指定type屬性,這時將通過反射機制使用byName自動注入策略。
  • @Autowired是spring的註解,是spring2.5版本引入的,Autowired只根據type進行注入,不會去匹配name。如果涉及到type無法辨別注入對象時,那需要依賴@Qualifier或@Primary註解一起來修飾。

     案例分析:

     我們創建一個簡單的springboot項目demo,

         定義:一個實現類Man.java

                    一個Service 接口Human.java,裏面一個方法 runMarathon,

                    一個Controller類HumanController.java,裏面注入Human接口的實現

           

           附各Java類源碼:

package com.example.annotation.service;
 
/**
 * service接口定義
 * @author Administrator
 */
public interface Human {
    
    /**
     * 跑馬拉松
     * @return
     */
    String runMarathon();
}
 
package com.example.annotation.service.impl;
 
import com.example.annotation.service.Human;
import org.springframework.stereotype.Service;
 
/**
 * service接口第一實現類
 * @author Administrator
 */
@Service
public class Man implements Human {
 
    public String runMarathon() {
        return "A man run marathon";
    }
}
 
package com.example.annotation.controller;
 
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.annotation.service.Human;
 
/**
 * controller層實現類
 * @author Administrator
 */
@RestController
@RequestMapping("/an")
public class HumanController {
 
    @Resource
    private Human human;
    
    @RequestMapping("/run")
    public String runMarathon() {
        return human.runMarathon();
    }
}


           至此,代碼整理完成,啓動springboot,瀏覽器地址欄輸入http://localhost:8080/an/run

改動一:

將HumanController.java 類中的註解替換爲@Autowired,再次啓動,可以正常訪問,與上圖相同,這裏不再貼訪問結果圖。

改動二:

再增加一個實現類Woman.java

package com.example.annotation.service.impl;
 
import com.example.annotation.service.Human;
import org.springframework.stereotype.Service;
 
/**
 * service接口第二實現類
 * @author Administrator
 */
@Service
public class Woman implements Human {
 
    public String runMarathon() {
        return "An woman run marathon";
    }
}


HumanController.java 註解使用@Resource

    @Resource
    private Human human;


啓動springboot,控制檯會報錯,報錯信息太多,截取關鍵信息

2018-09-10 16:07:10.362  WARN 5592 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'humanController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.annotation.service.Human' available: expected single matching bean but found 2: man,woman


找關鍵信息 expected single matching bean but found 2: man,woman,被期望的單一結果被匹配到兩個結果man和woman。

這裏,我們需要藉助@Resource註解的name屬性或@Qualifier來確定一個合格的實現類

代碼修改爲 

  @Resource(name="woman")
  private Human human;

或 

    @Resource
    @Qualifier("woman")
    private Human human;


上面,我們指定了Human接口的實現類是Woman.java,啓動springboot,訪問 http://localhost:8080/an/run

改動三:

在改動二的基礎上,將註解替換爲@Autowired,啓動報錯。

Description:
 
Field human in com.example.annotation.controller.HumanController required a single bean, but 2 were found:
	- man: defined in file [D:\DEV_ENV\springbootws\annotation\target\classes\com\example\annotation\service\impl\Man.class]
	- woman: defined in file [D:\DEV_ENV\springbootws\annotation\target\classes\com\example\annotation\service\impl\Woman.class]
 
 
Action:
 
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

報錯信息很明顯,HumanController需要一個bean實現,但是找到了兩個 man 和woman

解決方案:使用@Primary註解,在有多個實現bean時告訴spring首先@Primary修飾的那個;或者使用@Qualifier來標註需要注入的類。

@Qualifier修改方式與改動二的相同,依然是修改HumanController.java 中間注入的Human上面,這裏不再複述

@Primary是修飾實現類的,是告訴spring,如果有多個實現類時,優先注入被@Primary註解修飾的那個。這裏,我們希望注入Man.java ,那麼修改Man.java爲

package com.example.annotation.service.impl;
 
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import com.example.annotation.service.Human;
 
/**
 * service接口第一實現類
 * @author Administrator
 */
@Service
@Primary
public class Man implements Human {
 
    public String runMarathon() {
        return "A man run marathon";
    }
}


啓動springboot後,可以看到注入的已經是Man.java 了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章