public interface BeanNameGenerator { String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry); }这个方法有两个参数:
DefaultBeanNameGenerator:这个是专门用来解决 XML 文件中定义的 Bean 如果没有设置 beanName,那么就通过 DefaultBeanNameGenerator 来为其生成 beanName。
@Override public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { if (definition instanceof AnnotatedBeanDefinition) { String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition); if (StringUtils.hasText(beanName)) { // Explicit bean name found. return beanName; } } // Fallback: generate a unique default bean name. return buildDefaultBeanName(definition, registry); }这个方法首先判断 definition 是否为 AnnotatedBeanDefinition 类型,根据我们前面文章对 BeanDefinition 的介绍(七种 BeanDefinition,各显其能!),大家知道,AnnotatedBeanDefinition 的实现类主要是针对三种情况:@Bean 注解定义的 Bean、@Service/@Controller/@Component/@Repository 等注解标记的 Bean 以及系统的启动配置类,如果是这三种情况,那么就去调用 determineBeanNameFromAnnotation 方法,这个方法会尝试从注解中提取出来 beanName,如果不是上面三种情况,那么就调用 buildDefaultBeanName 方法去生成 beanName。
@Nullable protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) { AnnotationMetadata amd = annotatedDef.getMetadata(); Set<String> types = amd.getAnnotationTypes(); String beanName = null; for (String type : types) { AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type); if (attributes != null) { Set<String> metaTypes = this.metaAnnotationTypesCache.computeIfAbsent(type, key -> { Set<String> result = amd.getMetaAnnotationTypes(key); return (result.isEmpty() ? Collections.emptySet() : result); }); if (isStereotypeWithNameValue(type, metaTypes, attributes)) { Object value = attributes.get("value"); if (value instanceof String strVal) { if (StringUtils.hasLength(strVal)) { if (beanName != null && !strVal.equals(beanName)) { throw new IllegalStateException("Stereotype annotations suggest inconsistent " + "component names: '" + beanName + "' versus '" + strVal + "'"); } beanName = strVal; } } } } } return beanName; }这个方法首先会去获取类上的注解信息,拿到 amd 之后,获取到所有的注解类型,然后进行遍历。
@Configuration("j") @Component("a") public class JavaConfig { }这两个 beanName 不一致,运行时就会出错。
@Retention(RetentionPolicy.RUNTIME) @Component public @interface MyBeanName { String value() default ""; }这个注解衍生自 @Component,那么它的用法如下:
@MyBeanName("f") public class JavaConfig { }那么 f 就是当前类生成的 beanName。
protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { return buildDefaultBeanName(definition); } protected String buildDefaultBeanName(BeanDefinition definition) { // 堆代码 duidaima.com String beanClassName = definition.getBeanClassName(); Assert.state(beanClassName != null, "No bean class name set"); String shortClassName = ClassUtils.getShortName(beanClassName); return StringUtils.uncapitalizeAsProperty(shortClassName); }这个就很好懂了,先拿到 bean 的完整类名,然后提取出来 shortName,也就是去除包名之后的名字,然后首字母小写之后返回。这就是 @Component 注解体系下的 beanName 生成流程。
@Override protected String buildDefaultBeanName(BeanDefinition definition) { String beanClassName = definition.getBeanClassName(); Assert.state(beanClassName != null, "No bean class name set"); return beanClassName; }重写后的方法就是获取类的完整路径返回。
@Configuration @ComponentScan(nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class) public class JavaConfig { }此时,生成的 Bean 的默认名称就是类的全路径了。