spring beanname是如何生成的, 他的生成规则是什么?

付出努力但失败,是仅次于付出努力并成功的,世上第二棒的事

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

spring beanname是如何生成的, 他的生成规则是什么?_第1张图片

正是实现了 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”。

你可能感兴趣的:(spring,spring,java,后端)