Tao
Tao

Spring Bean Naming Conventions

In Spring, each bean has one or more identifiers that must be unique within the container where the bean resides. Typically, a bean has a single identifier, but aliases can be used to extend the identifiers if needed. In XML-based configuration, developers can specify bean identifiers using the id or name attributes. Generally, identifiers are composed of letters and may include special characters. If aliases are used, they can be separated by commas , or semicolons ; in the name attribute. The id or name attributes are not mandatory; if left empty, the container will automatically generate a unique name for the bean. Although there are no strict naming restrictions, the official recommendation is to follow camelCase conventions, which align with Java naming conventions.

The Spring framework provides the BeanNameGenerator interface to generate bean names by default. There are two main implementations: DefaultBeanNameGenerator and AnnotationBeanNameGenerator.

The DefaultBeanNameGenerator is the standard implementation used to generate bean names. Here is the implementation in detail:

java

public class DefaultBeanNameGenerator implements BeanNameGenerator {
    @Override
    public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
        return BeanDefinitionReaderUtils.generateBeanName(definition, registry);
    }
}

public class BeanDefinitionReaderUtils {
    public static String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry registry)
            throws BeanDefinitionStoreException {
        return generateBeanName(beanDefinition, registry, false);
    }

    public static String generateBeanName(
            BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean)
            throws BeanDefinitionStoreException {
        String generatedBeanName = definition.getBeanClassName();
        if (generatedBeanName == null) {
            if (definition.getParentName() != null) {
                generatedBeanName = definition.getParentName() + "$child";
            } else if (definition.getFactoryBeanName() != null) {
                generatedBeanName = definition.getFactoryBeanName() + "$created";
            }
        }
        if (!StringUtils.hasText(generatedBeanName)) {
            throw new BeanDefinitionStoreException("Unnamed bean definition specifies neither " +
                    "'class' nor 'parent' nor 'factory-bean' - can't generate bean name");
        }
        String id = generatedBeanName;
        if (isInnerBean) {
            id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition);
        } else {
            return uniqueBeanName(generatedBeanName, registry);
        }
        return id;
    }

    public static String uniqueBeanName(String beanName, BeanDefinitionRegistry registry) {
        String id = beanName;
        int counter = -1;
        while (counter == -1 || registry.containsBeanDefinition(id)) {
            counter++;
            id = beanName + GENERATED_BEAN_NAME_SEPARATOR + counter;
        }
        return id;
    }
}

The AnnotationBeanNameGenerator is used for generating bean names based on annotations. Here is its implementation:

java

public class AnnotationBeanNameGenerator implements BeanNameGenerator {
    @Override
    public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
        if (definition instanceof AnnotatedBeanDefinition) {
            String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
            if (StringUtils.hasText(beanName)) {
                return beanName;
            }
        }
        return buildDefaultBeanName(definition, registry);
    }
}

For beans registered using @Bean, if the name attribute is not specified, the default bean name is the method name:

java

@Configuration
public class ConfigurationClassBeanDefinitionReader {
    public void loadBeanDefinitionsForBeanMethod(...) {
        // Key code
        List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
        String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
    }
}

This article provides a detailed explanation of Spring bean naming conventions and analyzes the related source code. I hope this information is helpful for your Spring development.

Related Content