一文了解BeanNameGenerator
前言
在springboot
的项目中,我们会使用到很多的注解,比如@Service
,@Bean
等,添加这些注解SpringBoot
框架会帮忙创建bean
,并且用唯一的名字来区分,那我们就来看看源是怎么实现的吧。
相关源码
BeanNameGenerator接口
如下是BeanNameGenerator
接口代码,在代码中有一个generateBeanName
的方法,接下来看看该方法的具体实现。
public interface BeanNameGenerator {
/**
* Generate a bean name for the given bean definition.
* @param definition the bean definition to generate a name for
* @param registry the bean definition registry that the given definition
* is supposed to be registered with
* @return the generated bean name
*/
String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry);
}
如下图所示:该方法有很多的实现,比如XML
,注解, ClassPath
等
由于我们在代码中常用注解的方式来注册一个bean
,因此我们来继续看看AnnotationBeanNameGenerator
类,它实现了BeanNameGenerator
接口,具体看如下的代码:
AnnotationBeanNameGenerator实现类
public class AnnotationBeanNameGenerator implements BeanNameGenerator {
private static final String COMPONENT_ANNOTATION_CLASSNAME = "org.springframework.stereotype.Component";
@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);
}
在AnnotationBeanNameGenerator
类中,实现了generateBeanName
方法,在该方法中,使用determineBeanNameFromAnnotation
解析出definition
中的bean
名字。具体看看代码:
/**
* Derive a bean name from one of the annotations on the class.
* @param annotatedDef the annotation-aware bean definition
* @return the bean name, or {@code null} if none is found
*/
@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 && isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) {
Object value = attributes.get("value");
if (value instanceof String) {
String strVal = (String) value;
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;
}
在该方法中,对传入的参数annotatedDef
提取元数据,提取注解的类型,接着在for
循环中使用AnnotationConfigUtils
解析出attributes
,然后从attributes
提取出value
,即bean
的名字。