在 Spring中,id 和 name 命名 Bean 有什么區(qū)別?
首先,讓我們來看下Spring XML配置方式,id和name是如何定義Bean的:
<!-- 用id定義 -->
<bean id="userService" class="com.example.UserService"/>
<!-- 用name定義 -->
<bean name="userService" class="com.example.UserService"/>
接著,我們看一個注解方式:
// 注解方式
@Service("userService")
public class UserService {}
那么,問題來了:注解中的@Service("userService")相當于 XML中的 id還是 name?
這篇文章,我們來聊一聊。
1. 歷史背景
在早期的Spring版本(1.x時代):
- id屬性:必須符合 XML ID規(guī)范(不能有特殊字符,不能以數(shù)字開頭等)
- name屬性:更靈活,可以用各種字符,還能定義多個別名
這就導致很多開發(fā)者因為 XML規(guī)范限制不得不使用name。
但是!在Spring 3.1之后,id屬性不再受XML ID規(guī)范約束了,現(xiàn)在它和name在靈活性上已經(jīng)平起平坐了。
2. 原理剖析
本質(zhì)相同:無論是id還是name,最終都會變成 Bean的標識符(identifier)。
特殊之處:
- id:一個 Bean只能有一個id
- name:可以定義多個,用逗號/分號/空格分隔,相當于給Bean起別名,
<bean name="userService,userManager,userApi" class="com.example.UserService"/>
查找順序:當使用getBean()時,Spring會先查id,再查 name
3. 如何獲取 bean?
場景1:簡單Bean定義
// 注解方式
@Service("userService") // 這相當于xml中的id還是name?
public class UserService {}
對于@Service("xxx")中的名稱既會作為id,也會作為 name注冊!這個也回到了我們文章開頭的問題。
場景2:需要別名的情況
<bean id="mainDataSource" name="primaryDB,defaultDB" class="com.example.DataSource"/>
這時候用 name定義別名就很方便,代碼中可以根據(jù)不同場景使用不同名稱獲取同一個Bean。
場景3:帶有特殊字符的Bean名
<bean name="/api/user" class="com.yuanjava.UserController"/>
雖然現(xiàn)在 id也支持特殊字符了,但看到name="/api/user"這樣的寫法,是不是更符合咱們的直覺?
4. id和name有區(qū)別嗎?
通過上面的分析,你覺得id和name命名Bean在性能上會有差異嗎?
答案是:幾乎沒有區(qū)別!因為Spring內(nèi)部會把它們統(tǒng)一處理成標識符,選擇id或name不會影響應用性能。
經(jīng)過這么多年的踩坑,我的建議是:
- 默認使用id:因為它更語義化,表示唯一標識
- 需要別名時加上name:兩者可以共存!
<bean id="userService" name="userManager,userApi" class="com.example.UserService"/>
- 團隊統(tǒng)一規(guī)范:比選擇哪個更重要!
5. 總結(jié)
本文,我們分析了id和name命名的歷史,區(qū)別,以及如何在應用中使用它們:
- 如果你的Bean需要一個明確的、唯一的標識,請用id命名Bean
- 如果需要靈活性、多個名稱,請用name命名Bean
- 其實在Spring的現(xiàn)代版本中,它們的差別已經(jīng)很小了,最關(guān)鍵是保持一致性
好的命名是成功的一半,在 Spring世界里,id和name就像你的左右手,關(guān)鍵是要知道什么時候用哪只!