Spring之---@Primary 和 @Qualifier


本文轉載自:https://blog.csdn.net/u012260238/article/details/81110136

一、@Qualifier

一般情況下:在Controller中需要注入service,一般用@Reource( 默認按名稱裝配,當找不到與名稱匹配的bean才會按類型裝配)  和

                        @Autowired(默認按類型裝配,如果我們想使用按名稱裝配,可以結合@Qualifier注解一起使用)

一般情況下使用@@Autowired時:
那么這個service有兩個實現類如何區分開這兩個impl呢?

請看下面的例子:

接口:

1  public interface EmployeeService {
2     public EmployeeDto getEmployeeById(Long id);
3  }

接口對應的兩個實現類:EmployeeServiceImpl和EmployeeServiceImpl1:接口對應的兩個實現類:EmployeeServiceImpl和EmployeeServiceImpl1:

1 @Service("employeeService")
2 public class EmployeeServiceImpl implements EmployeeService {
3     public EmployeeDto getEmployeeById(Long id) {
4                 return new EmployeeDto();
5      }
6 }
1 @Service("employeeService1")
2 public class EmployeeServiceImpl1 implements EmployeeService {
3     public EmployeeDto getEmployeeById(Long id) {
4          return new EmployeeDto();
5     }
6 }

調用代碼如下:

 1 @Controller
 2 @RequestMapping("/emplayee.do")
 3 public class EmployeeInfoControl {
 4     @Autowired
 5     EmployeeService employeeService;
 6              
 7     @RequestMapping(params = "method=showEmplayeeInfo")
 8     public void showEmplayeeInfo(HttpServletRequest request, HttpServletResponse response, EmployeeDto dto) {
 9                 #略
10     }
11 }

 在啟動tomcat時報如下錯誤:
  org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employeeInfoControl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.test.service.EmployeeService com.test.controller.EmployeeInfoControl.employeeService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.test.service.EmployeeService] is defined: expected single matching bean but found 2: [service1, service2]
  --》  其實報錯信息已經說得很明確了,在@Autowired時,由於有兩個類實現了EmployeeService接口,所以Spring不知道應該綁定哪個實現類,所以拋出了如上錯誤。
   這個時候就要用到@Qualifier注解了,qualifier的意思是合格者,通過這個標示,表明了哪個實現類才是我們所需要的,我們修改調用代碼,添加@Qualifier注解,需要注意的是@Qualifier的參數名稱必須為我們之前定義@Service注解的名稱之一!

 1  @Controller
 2  @RequestMapping("/emplayee.do")
 3 public class EmployeeInfoControl {
 4     
 5     @Autowired
 6     @Qualifier("employeeService")  7     EmployeeService employeeService;
 8     
 9     @RequestMapping(params = "method=showEmplayeeInfo")
10     public void showEmplayeeInfo(HttpServletRequest request, HttpServletResponse response, EmployeeDto dto) {
11             #略
12     }
13 }

 二、@Primary:和@Qualifier 一樣,@Primary也一樣,使用場景經常是:在spring 中使用注解,常使用@Autowired, 默認是根據類型Type來自動注入的。但有些特殊情況,對同一個接口,可能會有幾種不同的實現類,而默認只會采取其中一種的情況下 @Primary 的作用就出來了。

簡單例子:

接口:

 

1 public interface Singer {
2     String sing(String lyrics);
3 }

 

有下面的兩個實現類:

1 @Component // 加注解,讓spring識別
2 public class MetalSinger implements Singer{
3 
4     @Override
5     public String sing(String lyrics) {
6         return "I am singing with DIO voice: "+lyrics;
7     }
8 }
1 //注意,這里沒有注解
2 public class OperaSinger implements Singer {
3     @Override
4     public String sing(String lyrics) {
5         return "I am singing in Bocelli voice: "+lyrics;
6     }
7 }

下面就是注入上面的接口實現類:

 1 @Component
 2 public class SingerService {
 3     private static final Logger logger = LoggerFactory.getLogger(SingerService.class);
 4 
 5     @Autowired
 6     private Singer singer;
 7 
 8     public String sing(){
 9         return singer.sing("song lyrics");
10     }
11 }

結果:I am singing with DIO voice: song lyrics.

原因很簡單,就是 OperaSinger 這個類上面根本沒有加上注解@Copmonent 或者 @Service, 所以spring 注入的時候,只能找到 MetalSinger 這個實現類. 所以才有這個結果。

但是如果一旦 OperaSinger 這個類加上了@Copmonent 或者 @Service 注解,有趣的事情就會發生,你會發現一個錯誤的結果或異常:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [main.service.Singer] is defined: expected single matching bean but found 2: metalSinger,operaSinger

提示很

1 @Primary
2 @Component
3 public class OperaSinger implements Singer{
4 
5     @Override
6     public String sing(String lyrics) {
7         return "I am singing in Bocelli voice: "+lyrics;
8     }
9 }

如果代碼改成這樣,再次運行,結果如下:
“I am singing in Bocelli voice: song lyrics”, 用@Primary 告訴spring 在猶豫的時候優先選擇哪一個具體的實現。

明確了,spring 根據類型無法選擇到底注入哪一個。這個時候@Primay 可以閃亮登場了。

三、擴展:Spring注解常用匯總

使用注解之前要開啟自動掃描功能

其中base-package為需要掃描的包(含子包)

 

@Configuration把一個類作為一個IoC容器,它的某個方法頭上如果注冊了@Bean,就會作為這個Spring容器中的Bean。
@Scope注解 作用域
@Lazy(true) 表示延遲初始化
@Service用於標注業務層組件、
@Controller用於標注控制層組件(如struts中的action)
@Repository用於標注數據訪問組件,即DAO組件。
@Component泛指組件,當組件不好歸類的時候,我們可以使用這個注解進行標注。
@Scope用於指定scope作用域的(用在類上)
@PostConstruct用於指定初始化方法(用在方法上)
@PreDestory用於指定銷毀方法(用在方法上)
@Resource 默認按名稱裝配,當找不到與名稱匹配的bean才會按類型裝配。
@DependsOn:定義Bean初始化及銷毀時的順序
@Primary:自動裝配時當出現多個Bean候選者時,被注解為@Primary的Bean將作為首選者,否則將拋出異常
@Autowired 默認按類型裝配,如果我們想使用按名稱裝配,可以結合@Qualifier注解一起使用
@Autowired @Qualifier("personDaoBean") 存在多個實例配合使用

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM