闽公网安备 35020302035485号
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 的默认名称就是类的全路径了。