Spring @Autowired 注入小技巧

擁抱心中的夢想發表於2018-07-23

今天和同事討論到Spring自動注入時,發現有這麼一段程式碼特別地困惑,當然大致的原理還是可以理解的,只不過以前從來沒有這麼用過。想到未來可能會用到,或者未來看別人寫的程式碼時不至於花時間解決同樣的困惑,所以小編還是覺得有必要研究記錄一下。

一、同一型別注入多次為同一例項

首先讓我們先看下這段程式碼是什麼?

@Autowired
private XiaoMing xiaoming;

@Autowired
private XiaoMing wanger;
複製程式碼

XiaoMing.java

package com.example.demo.beans.impl;

import org.springframework.stereotype.Service;

/**
 * 
 * The class XiaoMing.
 *
 * Description:小明
 *
 * @author: huangjiawei
 * @since: 2018年7月23日
 * @version: $Revision$ $Date$ $LastChangedBy$
 *
 */
@Service
public class XiaoMing {
    
    public void printName() {
    	System.err.println("小明");
    }
}
複製程式碼

我們都知道@Autowired可以根據型別(Type)進行自動注入,並且預設注入的bean為單例(SingleTon)的,那麼我們可能會問,上面注入兩次不會重複嗎?答案是肯定的。而且每次注入的例項都是同一個例項。下面我們簡單驗證下:

@RestController
public class MyController {
    
    @Autowired
    private XiaoMing xiaoming;
    
    @Autowired
    private XiaoMing wanger;
    
    @RequestMapping(value = "/test.json", method = RequestMethod.GET)
    public String test() {
    	System.err.println(xiaoming);
    	System.err.println(wanger);
    	return "hello";
    }
}
複製程式碼

呼叫上面的介面之後,將輸出下面內容,可以看出兩者為同一例項。

com.example.demo.beans.impl.XiaoMing@6afd4ce9
com.example.demo.beans.impl.XiaoMing@6afd4ce9
複製程式碼

二、注入介面型別例項

如果我們要注入的型別宣告為一個介面型別,而且該介面有1個以上的實現類,那麼下面這段程式碼還能夠正常執行嗎?我們假設Student為介面,WangErXiaoMing為兩個實現類。

@Autowired
private Student stu1;

@Autowired
private Student stu2;
複製程式碼
@Service
public class XiaoMing implements Student {
複製程式碼
@Service
public class WangEr implements Student {
複製程式碼

答案是上面的程式碼不能正常執行,而且Spring 還啟動報錯了,原因是Spring想為Student注入一個單例的例項,但在注入的過程中意外地發現兩個,所以報錯,具體錯誤資訊如下:

Field stu1 in com.example.demo.controller.MyController required a single bean, but 2 were found:
	- wangEr: defined in file [C:\Users\huangjiawei\Desktop\demo\target\classes\com\example\demo\beans\impl\WangEr.class]
	- xiaoMing: defined in file [C:\Users\huangjiawei\Desktop\demo\target\classes\com\example\demo\beans\impl\XiaoMing.class]
複製程式碼

那該怎麼弄才行呢?一般思路我們會想到為每個實現類分配一個id值,結果就有了下面的程式碼:

@Autowired
private Student stu1;

@Autowired
private Student stu2;
複製程式碼
@Service("stu1")
public class XiaoMing implements Student {
複製程式碼
@Service("stu2")
public class WangEr implements Student {
複製程式碼

做完上面的配置之後,Spring就會根據欄位名稱預設去bean工廠找相應的bean進行注入,注意名稱不能夠隨便取的,要和注入的屬性名一致。

三、總結

  • 1、同一型別可以使用@Autowired注入多次,並且所有注入的例項都是同一個例項;
  • 2、當對介面進行注入時,應該為每個實現類指明相應的id,則Spring將報錯;

相關文章