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
//这里是栈顶