今天和同事討論到spring自動注入時,發現有這么一段代碼特別地困惑,當然大致的原理還是可以理解的,只不過以前從來沒有這么用過。想到未來可能會用到,或者未來看別人寫的代碼時不至于花時間解決同樣的困惑,所以小編還是覺得有必要研究記錄一下。
一、同一類型注入多次為同一實例
首先讓我們先看下這段代碼是什么?
1
2
3
4
5
|
@autowired private xiaoming xiaoming; @autowired private xiaoming wanger; |
xiaoming.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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
)的,那么我們可能會問,上面注入兩次不會重復嗎?答案是肯定的。而且每次注入的實例都是同一個實例。下面我們簡單驗證下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@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
為接口, wanger
和 xiaoming
為兩個實現類。
1
2
3
4
5
|
@autowired private student stu1; @autowired private student stu2; |
1
2
|
@service public class xiaoming implements student { |
1
2
|
@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值,結果就有了下面的代碼:
1
2
3
4
5
|
@autowired private student stu1; @autowired private student stu2; |
1
2
|
@service ( "stu1" ) public class xiaoming implements student { |
1
2
|
@service ( "stu2" ) public class wanger implements student { |
做完上面的配置之后,spring就會根據字段名稱默認去bean工廠找相應的bean進行注入,注意名稱不能夠隨便取的,要和注入的屬性名一致。
三、總結
-
1、同一類型可以使用
@autowired
注入多次,并且所有注入的實例都是同一個實例; - 2、當對接口進行注入時,應該為每個實現類指明相應的id,則spring將報錯;
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://juejin.im/post/5b557331e51d45191c7e64d2