付出努力但失败,是仅次于付出努力并成功的,世上第二棒的事
debug 走起
org.springframework.context.annotation.ComponentScanAnnotationParser#parse
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));
org.springframework.context.annotation.ConfigurationClassParser#ConfigurationClassParser
->
org.springframework.context.annotation.ConfigurationClassPostProcessor#componentScanBeanNameGenerator
@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);
}
通过接口 AnnotatedBeanDefinition 判断是否是有注解的
我们这里是 ScannedGenericBeanDefinition
正是实现了 AnnotatedBeanDefinition 的类,
用接口判断这个真是妙呀,
不用再去通过反射获取注解信息判断, 真是强呀
然后通过 determineBeanNameFromAnnotation 注解方法获取到component注解是否自定义了名字
其实只要定义以下标签都可以
protected boolean isStereotypeWithNameValue(String annotationType,
Set<String> metaAnnotationTypes, @Nullable Map<String, Object> attributes) {
boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) ||
metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME) ||
annotationType.equals("javax.annotation.ManagedBean") ||
annotationType.equals("javax.inject.Named");
return (isStereotype && attributes != null && attributes.containsKey("value"));
}
最后没办法没有配置, 默认使用 buildDefaultBeanName 生成默认的方法
protected String buildDefaultBeanName(BeanDefinition definition) {
String beanClassName = definition.getBeanClassName();
Assert.state(beanClassName != null, "No bean class name set");
String shortClassName = ClassUtils.getShortName(beanClassName);
return Introspector.decapitalize(shortClassName);
}
decapitalize 方法实现
public static String decapitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
Character.isUpperCase(name.charAt(0))){
return name;
}
char chars[] = name.toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}
获取字符串并将其转换为普通 Java 变量名称大写的实用程序方法。这通常意味着将第一个字符从大写转换为小写,但在特殊情况下,当有多个字符而且第一个和第二个字符都是大写时,类名就是BeanName。因此,“FooBah”变成了“fooBah”,“X”变成了“x”,但“URL”仍然是“URL”。