付出努力但失败,是仅次于付出努力并成功的,世上第二棒的事
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
@Overridepublic 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”。