记一次@Component无效的问题

1. 问题描述

具体的业务就不说了

抽象出来的问题是, 有一个类 标记了 @Aspect@Component ,但是切面却没有起作用

applicationContext.getBean(XXX.class);
//找不到这个bean,很奇怪

2. 查原因

  1. 打断点,查看BeanFactory里面的所有BeanDefinition,发现没有XXX这个类
  2. BeanFactory使用了一个Map来存储所有的BeanDefinition, 考虑是否是key重复的原因
  3. 找到生成Bean名称的类 org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName ,发现如果未指定名称,则使用,如下代码来生成Bean的名字
protected String buildDefaultBeanName(BeanDefinition definition) {
    String shortClassName = ClassUtils.getShortName(definition.getBeanClassName());
    return Introspector.decapitalize(shortClassName);
}
  1. 打一个条件断点,查看输出的名字, 发现真的有两个BeanDefinition名字重复了,包名不一样,类名是一样的
  2. 问题找到了,在扫描所有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
//这里是栈顶

你可能感兴趣的:(工作问题)