spring框架對(duì)于不同包下同名類的查找問題

??

問題背景

在使用dubbo的時(shí)候突然想到如果不同提供者的類名一樣的話那調(diào)用時(shí)怎么辦(因?yàn)檎{(diào)用提供者的服務(wù)包名結(jié)構(gòu)必須要一致)披泪。于是找了一下這個(gè)問題

問題分析

(可能比較冗余,如果不想看可以直接跳結(jié)論)
java描述一個(gè)類(相同加載器假褪,相同虛擬機(jī))歼疮,確實(shí)是依賴類的完整名(包名+類名)杂抽,也就是說,不同包下的同名類韩脏,互相完全沒有關(guān)系缩麸,是兩個(gè)完全不同的類。但spring對(duì)這種類的處理卻和這種方式不同赡矢。很有趣的問題杭朱,因此決定把它搞清楚阅仔。

是spring中,被它所管理的類是通過BeanDefinition來描述的弧械,而注冊(cè)一個(gè)bean八酒,是通過這個(gè)函數(shù)registerBeanDefinition(String beanName, BeanDefinition beanDefinition)進(jìn)行的。
最終bean會(huì)被存儲(chǔ)在這樣一個(gè)map里:private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
現(xiàn)在的報(bào)錯(cuò)原因刃唐,就是因?yàn)樵谧?cè)bean之前羞迷,對(duì)beanName做了唯一性驗(yàn)證,而這個(gè)驗(yàn)證正好失敗画饥。
我們繼續(xù)看spring的源碼

//掃碼獲取bean的主要函數(shù)
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
    for (String basePackage : basePackages) {
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); //獲取beanName
            if (candidate instanceof AbstractBeanDefinition) {
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition) {
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            if (checkCandidate(beanName, candidate)) { //該步報(bào)錯(cuò),conflicts
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                definitionHolder =
                            AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}

現(xiàn)在問題變成了為什么beanNameGenerator.generateBeanName(candidate, this.registry);會(huì)返回類名衔瓮,而不是package+類名。
我們繼續(xù)看generateBeanName的實(shí)現(xiàn)抖甘,有兩個(gè)實(shí)現(xiàn)

DefaultBeanNameGenerator
AnnotationBeanNameGenerator

先看DefaultBeanNameGenerator的實(shí)現(xiàn)热鞍,它的實(shí)現(xiàn)相對(duì)簡(jiǎn)單,核心代碼是這句String generatedBeanName = definition.getBeanClassName();而它的實(shí)現(xiàn)如下

@Override
public String getBeanClassName() {
    Object beanClassObject = this.beanClass;
    if (beanClassObject instanceof Class) {
        return ((Class<?>) beanClassObject).getName(); //返回類的完整名单山,packageName + className
    }
    else {
        return (String) beanClassObject;
    }
}

也就是說碍现,DefaultBeanNameGenerator返回的beanName是packageName+beanName。

總結(jié)

spring并不支持不同的包下類名相同的設(shè)定米奸。這是因?yàn)槟J(rèn)的spring檢索bean的唯一id(@Service,@Component等)為bean的name昼接,并不包含package name信息。想要規(guī)避這種問題有兩種方式
a 對(duì)bean顯式命名悴晰,@Service("yourName")
b 使用xml的方式聲明bean

在調(diào)用同名的類時(shí)第二個(gè)需要寫全包名結(jié)構(gòu)慢睡,使用 @Qualifier 注釋和 @Autowired 注釋通過指定哪一個(gè)真正的 bean 將會(huì)被裝配來消除混亂。如:

@RestController
public class TestController {

    @Autowired
    private TestService testService;

    @Autowired @Qualifier("dTestService")
    private com.example.demo.service.TestService t2;

    @RequestMapping(value = "t")
    public String testt(String str){
        return t2.s1(str);
    }

    @RequestMapping(value = "d")
    public String testd(String str){
        return testService.testWord(str);
    }

    @RequestMapping(value = "test")
    public String test(String str){
        return "Hello "+str+" test";
    }
}

@Qualifier限定描述符除了能根據(jù)名字進(jìn)行注入铡溪,更能進(jìn)行更細(xì)粒度的控制如何選擇候選者

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末漂辐,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子棕硫,更是在濱河造成了極大的恐慌髓涯,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哈扮,死亡現(xiàn)場(chǎng)離奇詭異纬纪,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)滑肉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門包各,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人靶庙,你說我怎么就攤上這事问畅。” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵护姆,是天一觀的道長(zhǎng)矾端。 經(jīng)常有香客問我,道長(zhǎng)卵皂,這世上最難降的妖魔是什么须床? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮渐裂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘钠惩。我一直安慰自己柒凉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布篓跛。 她就那樣靜靜地躺著膝捞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪愧沟。 梳的紋絲不亂的頭發(fā)上蔬咬,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音沐寺,去河邊找鬼林艘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛混坞,可吹牛的內(nèi)容都是我干的狐援。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼究孕,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼啥酱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起厨诸,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤镶殷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后微酬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绘趋,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年得封,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了埋心。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡忙上,死狀恐怖拷呆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤茬斧,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布腰懂,位于F島的核電站,受9級(jí)特大地震影響项秉,放射性物質(zhì)發(fā)生泄漏绣溜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一娄蔼、第九天 我趴在偏房一處隱蔽的房頂上張望怖喻。 院中可真熱鬧,春花似錦岁诉、人聲如沸锚沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽哗蜈。三九已至,卻和暖如春坠韩,著一層夾襖步出監(jiān)牢的瞬間距潘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國打工只搁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留音比,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓须蜗,卻偏偏與公主長(zhǎng)得像硅确,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子明肮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1 問題背景由于厭倦了java里面冗長(zhǎng)的命名方式菱农,因此最近開始將文件名盡量的縮短。信息盡量通過包名來一層層描述柿估。這...
    littlersmall閱讀 8,796評(píng)論 0 51
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理循未,服務(wù)發(fā)現(xiàn),斷路器秫舌,智...
    卡卡羅2017閱讀 134,656評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,810評(píng)論 6 342
  • 你需要知道一些事的妖, 順便看一下人心。 很多看似堅(jiān)實(shí)的感情足陨, 都是沒有實(shí)質(zhì)根基的嫂粟。 它們流于表面, 它們情比金堅(jiān)墨缘, ...
    張梓潼閱讀 210評(píng)論 0 0
  • 早晨剛剛醒來時(shí)星虹,立刻喝一杯溫開水零抬,當(dāng)水在胃里短暫停留后,80%以上進(jìn)入小腸宽涌,并吸收入血平夜,21秒后將抵達(dá)身體的每一個(gè)...
    瑩小七閱讀 180評(píng)論 0 0