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)) { // 堆代码 duidaima.com // 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) { String beanClassName = definition.getBeanClassName(); Assert.state(beanClassName != null, "No bean class name set"); String shortClassName = ClassUtils.getShortName(beanClassName); return StringUtils.uncapitalizeAsProperty(shortClassName); }这个就很好懂了,先拿到 bean 的完整类名,然后提取出来 shortName,也就是去除包名之后的名字,然后首字母小写之后返回。
@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 的默认名称就是类的全路径了。
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) { // Consider name and any aliases List < String > names = new ArrayList < > (Arrays.asList(bean.getStringArray("name"))); String beanName = (!names.isEmpty() ? names.remove(0) : methodName); // Register aliases even when overridden for (String alias: names) { this.registry.registerAlias(beanName, alias); } }从这里可以看到,如果一开始配置了 name 属性,那么就把 names 集合中的第一个值拿出来作为 beanName,集合中的其他值则当作别名来处理,如果没有配置 name 属性值,那么就使用方法名作为 beanName。