记一次@Component无效的问题

本文描述了在Spring框架中使用AOP时遇到的一个问题:两个具有相同短类名但不同包名的@Component注解类导致Bean注册冲突,进而使Aspect切面失效。通过分析BeanName生成机制,发现重名Bean在BeanFactory的Map中被后扫描到的类覆盖,最终通过为其中一个类指定唯一Bean名称解决了问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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
//这里是栈顶
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值