詳解關于spring bean名稱命名的那些事
前言
用了多年spring,一直想當然把spring默認的beanName當成是類名的首字母小寫,比如HelloService其beanName為helloService。直到有天對接了供方廠商的接口,他有個類形如ABService,于是用
getBean(“aBService”)
的方式獲取bean,結果取到是null,一開始以為是ABservice沒注入,后面采用
getBean(ABService.class)
能成功獲取到bean,說明ABService是有注入到IOC容器中,但是為啥用aBService獲取不到bean?于是就用如下代碼段,打印出相應ABService對應的beanName
applicationContext.getBeansOfType(ABService.class).forEach((beanName,bean)->{
System.out.println(beanName + ":" + bean);
});
打印出來的結果,如下
ABService:com.github.lybgeek.ABService@245b6b85
beanName竟然是ABService,這就和之前的想當然有出入。于是只好查看源碼
02源碼查看
源碼查看有2種方式,本文的示例是springboot項目
01從main方法直接調試斷點

從圖可以看出如果是以掃描注解注入形式,其beanName的生成規(guī)則是由
org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName
決定。
ps: 這種直接從main啟動類調試起,比較適用于時間比較多,或者排查毫無頭緒
02帶著問題查看,靠猜加驗證的方式
利用idea的find Usage查找引用,比如ABService的注解@service,我們可以直接查看哪個引用到@Service,再猜測下beanName的生成規(guī)則

通過猜,我們基本上就可以定位出比較符合我們需求的方法
03源碼驗證
從上面的分析,我們可以知道如果是掃描bean注解注入的方式,其生成beanName規(guī)則,是在
org.springframework.context.annotation.AnnotationBeanNameGenerator
其生成規(guī)則代碼如下
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
if (definition instanceof AnnotatedBeanDefinition) {
String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
if (StringUtils.hasText(beanName)) {
// Explicit bean name found.
return beanName;
}
}
// Fallback: generate a unique default bean name.
return buildDefaultBeanName(definition, registry);
}
從代碼段,我們可以看出,注解上有取名,比如@Service(“abService”),則beanName為abService,如果沒有取名,則看
protected String buildDefaultBeanName(BeanDefinition definition) {
String beanClassName = definition.getBeanClassName();
Assert.state(beanClassName != null, "No bean class name set");
String shortClassName = ClassUtils.getShortName(beanClassName);
return Introspector.decapitalize(shortClassName);
}
public static String decapitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
Character.isUpperCase(name.charAt(0))){
return name;
}
char chars[] = name.toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}
其實從代碼我們就很容易看出答案了,如果類名前兩個或以上個字母都是大寫,則beanName和類名就一樣了,不會進行首字母小寫轉換。
decapitalize這個方法的注釋也寫得很清楚,注釋如下
/**
* Utility method to take a string and convert it to normal Java variable
* name capitalization. This normally means converting the first
* character from upper case to lower case, but in the (unusual) special
* case when there is more than one character and both the first and
* second characters are upper case, we leave it alone.
* <p>
* Thus "FooBah" becomes "fooBah" and "X" becomes "x", but "URL" stays
* as "URL".
*
* @param name The string to be decapitalized.
* @return The decapitalized version of the string.
*/
04總結
通過掃描bean注解注入IOC時,如果不指定bean名稱的默認規(guī)則是類名的首字母小寫,如果類名前兩個或以上個字母都是大寫,那么bean名稱與類名一樣。
其實這個細節(jié)可能懂的都懂,本文的彩蛋主要是分享一下平時查看源碼的一點心得吧,哈哈
到此這篇關于spring bean名稱命名的文章就介紹到這了,更多相關spring bean名稱命名內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
java實現(xiàn)二叉樹的創(chuàng)建及5種遍歷方法(總結)
下面小編就為大家?guī)硪黄猨ava實現(xiàn)二叉樹的創(chuàng)建及5種遍歷方法(總結)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04
SpringBoot HikariCP連接池監(jiān)控實現(xiàn)方案
文章介紹了五種監(jiān)控SpringBoot應用程序中HikariCP連接池狀態(tài)和性能的工具和技術,包括SpringBootActuator、Micrometer、Prometheus+Grafana、HikariCP自帶的Metrics以及NewRelic/Datadog等第三方服務,每種方法都有其特點和配置步驟2025-01-01
詳解Java的call by value和call by reference
在本篇文章里小編給大家總結了關于Java的call by value和call by reference的相關用法和知識點內容,需要的朋友們學習下。2019-03-03
java8新特性之stream流中reduce()求和知識總結
今天帶大家回顧Java8的新特性,文中對stream流中reduce()求和的相關知識作了詳細的介紹,對正在學習java的小伙伴們有很好地幫助,需要的朋友可以參考下2021-05-05
springboot結合前端實現(xiàn)網頁跳轉功能實例
今天處理Springboot統(tǒng)一異常攔截的時候,遇到了頁面跳轉的問題,這篇文章主要給大家介紹了關于springboot結合前端實現(xiàn)網頁跳轉功能的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2023-12-12

