1. 問題描述
具體的業務就不說了
抽象出來的問題是, 有一個類 標記了 @Aspect
和 @Component
,但是切面卻沒有起作用
applicationContext.getBean(XXX.class);
//找不到這個bean,很奇怪
2. 查原因
- 打斷點,查看
BeanFactory
裏面的所有BeanDefinition
,發現沒有XXX
這個類 BeanFactory
使用了一個Map來存儲所有的BeanDefinition
, 考慮是否是key重複的原因- 找到生成Bean名稱的類
org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName
,發現如果未指定名稱,則使用,如下代碼來生成Bean的名字
protected String buildDefaultBeanName(BeanDefinition definition) {
String shortClassName = ClassUtils.getShortName(definition.getBeanClassName());
return Introspector.decapitalize(shortClassName);
}
- 打一個條件斷點,查看輸出的名字, 發現真的有兩個
BeanDefinition
名字重複了,包名不一樣,類名是一樣的 - 問題找到了,在掃描所有
BeanDefinition
的時候, 重名的BeanDefinition
把先掃描到放入Map的給覆蓋掉了
3. 解決
直接給 重名的Bean改個名字 @Component("YYYYY")
即可
4. Spring環境啓動的方法棧如下
//這裏是棧底
org.springframework.context.support.AbstractApplicationContext#refresh
org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
org.springframework.context.support.AbstractApplicationContext#refreshBeanFactory
org.springframework.context.support.AbstractRefreshableApplicationContext#loadBeanDefinitions
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#scan
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
//String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
//這裏是生成Bean的名字的步驟
org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName
org.springframework.beans.factory.support.BeanDefinitionRegistry#registerBeanDefinition
//這裏是把BeanDefinition往map放的步驟
org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition
//這裏是棧頂