Spring Bean Naming: Default, Explicit and Custom Strategies

In Spring framework, every bean must have at least one name that is unique within the containing ApplicationContext. Spring follows simple and default naming strategies to determine the names for the beans, whether we use XML configuration or Java configuration. This article will discuss these strategies in detail.

Note that if multiple beans of the same type without explicit names are declared, Spring will throw a NoSuchBeanDefinitionException exception during ApplicationContext initialization.

1. Default Bean Naming with @Component

By default, Spring takes the simple name of the type declaring the bean, changes the first letter to lowercase, and uses the resulting value to name the bean. This is true for all stereotype annotations (@Service, @Repository, etc.).

When the component scanning is enabled, we can declare a very simple bean as follows:

@Configuration
@ComponentScan
public class AppConfig {
	//...
}

@Component
public class DemoBean { 

	//...
}

The DemoBean is annotated with @Component and is discovered via component scanning. When we retrieve the bean from the application context and print its name, it prints “demoBean“.

var applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
Arrays.stream(applicationContext.getBeanDefinitionNames()).forEach(System.out::println);

The program output:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.annotation.internalPersistenceAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
appConfig
demoBean

In the output, we can see the infrastructure beans created by Spring, and then the beans created by us appConfig and demoBean.

2. Default Bean Naming with @Bean

When we create a new bean using the @Bean annotation, the bean is named after the method that created it.

Let us understand with an example. We have removed the @Component annotation from DemoBean class.

public class DemoBean { 

	//...
}

Now we create two beans of type DemoBean with different method names.

@Configuration
public class AppConfig {

  @Bean
  DemoBean demoBean(){
    return new DemoBean();
  }

  @Bean
  DemoBean anotherDemoBean(){
    return new DemoBean();
  }
}

When we run the test code and print the bean names, we get the bean names based on the methods:

...
appConfig
demoBean
anotherDemoBean

3. Explicit Bean Naming with Values

For all stereotype annotations, there is a default attribute named value that can be initialized with a value to be used as a name for the bean.

@Component(value = "newBeanName")
public class DemoBean {
	//...
}

Note that @Component(value = "newBeanName") is equivalent to @Component("newBeanName"). They produce the same result.

Similarly, @Bean annotation has two attributes name and value that can be used to define an explicit name for the bean on which the annotation has been applied.

@Configuration
public class AppConfig {

  @Bean(name = "newBeanName")
  DemoBean demoBean(){
    return new DemoBean();
  }

  @Bean(value = "anotherNewBeanName")
  DemoBean anotherDemoBean(){
    return new DemoBean();
  }
}

When we again run the test code and print the bean names, we get the following:

...
appConfig
newBeanName
anotherNewBeanName

4. Bean Name Aliases: Multiple Bean Names

The name or value attributes of @Bean annotation can specify an array of values, referring to bean names. When it is done, the first one in the array becomes the name and the rest become aliases.

@Bean(value = {"newBeanName", "newBeanName-1", "newBeanName-2"})
DemoBean demoBean(){
  return new DemoBean();
}

Now when printing the bean name, it is still “newBeanName“. But when we print the bean name aliases, we get the additional names i.e. “newBeanName-1” and “newBeanName-2“.

var applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
Arrays.stream(applicationContext.getBeanDefinitionNames()).forEach(System.out::println);

var demoBean = applicationContext.getBeansOfType(DemoBean.class);

demoBean.forEach((k, v) -> {
  var aliases = applicationContext.getAliases(k);
  if (aliases.length > 0) {
    Arrays.stream(aliases).forEach(System.out::println);
  }
});

Program output:

...
appConfig
newBeanName
newBeanName-2
newBeanName-1

5. Generating Custom Bean Names

Similar to all features in Spring, the bean naming can also be customized. For custom name generation, we define a class that extends AnnotationBeanNameGenerator and specify its name in @ComponentScan annotation.

@Configuration
@ComponentScan(nameGenerator = CustomBeanNameGenerator.class)
public class AppConfig {
	//...
}

Then we define the custom name generation logic by overriding the buildDefaultBeanName() method in the CustomBeanNameGenerator class.

The following example returns the bean names composed from the lowercase simple class name concatenated with a unique identifier.

public class CustomBeanNameGenerator extends AnnotationBeanNameGenerator {

  @Override
  protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    var beanName = definition.getBeanClassName()
      .substring(definition.getBeanClassName().lastIndexOf(".") + 1)
      .toLowerCase(Locale.ROOT);
    var uid = UUID.randomUUID().toString().replace("-","").substring(0,8);
    return beanName + "-" + uid;
  }
}

When we run the test code again, the new custom name for bean is printed as:

appConfig
demobean-889ed00b

Notice that the name of infrastructure beans and appConfig bean is not modified because these are created before the CustomBeanNameGenerator bean during component scanning enabled through AppConfig class.

6. Conclusion

In this Spring tutorial, we discussed the default naming strategy that utilizes the class names or the method names depending on where the annotation has been used. We learned to use the value attribute to specify the explicit name and multiple aliases for bean names.

Finally, we learned to customize the naming strategy by extending the AnnotationBeanNameGenerator class. We saw the examples of each usecase with generated bean names.

Happy Learning !!

Source Code on Download

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode