1. Overview

In this quick tutorial, we're going to examine how we can name our Spring beans using the @Bean annotation.

2. Sample Application

Let's first look at our sample application.

We'll work with GreetingService and its only implementation, DefaultGreetingService:

public interface GreetingService {

    void greet();
}

public class DefaultGreetingService implements GreetingService {

    @Override
    public void greet() {
        System.out.println("Hi");
    }
}

Note that we don't have any annotation - i.e. @Component - on DefaultGreetingService since we'll define our beans using the @Bean annotation in a configuration class.

3. Default Bean Naming Strategy

To begin with, we'll look at the default bean naming strategy.

When a method is annotated with @Bean, without applying any further configuration, the method name becomes the bean name:

@Configuration
public class ApplicationConfiguration {

    @Bean
    public DefaultGreetingService greetingService() {
        return new DefaultGreetingService();
    }
}

Here, we have a bean definition for DefaultGreetingService in the ApplicationConfiguration class. Note that we aren't setting any attribute on the @Bean annotation. As a result, Spring registers the bean using the method name, greetingService.

Now that we have our bean defined, we'll use it for autowiring:

@Component
public class GreetingClient {

    @Autowired
    @Qualifier("greetingService")
    private GreetingService service1;
}

4. Define Bean Name with @Bean

Now, we'll explicitly define the bean names using the @Bean annotation.

We'll do this by setting the value or name attribute of @Bean:

@Bean({"firstGreetingService", "theGreetingService"})
public DefaultGreetingService serviceWithName() {
    return new DefaultGreetingService();
}

Here, we're defining two names: firstGreetingService and theGreetingService. Now we can access our bean using one of these names. However, when we define the bean names explicitly, Spring stops using the method name as the bean name:

@Component
public class GreetingClient {

    @Autowired
    @Qualifier("firstGreetingService")
    private GreetingService service2;

    @Autowired
    @Qualifier("theGreetingService")
    private GreetingService service3;
}

Here, we're autowiring the GreetingService bean with two different names.

5. Define Bean Name with @Qualifier

Lastly, we'll look at the @Qualifier annotation. We generally use @Qualifier when autowiring the beans on the client code. But now, we'll use it when defining a bean:

@Bean
@Qualifier("qualifiedGreetingService")
public DefaultGreetingService serviceWithQualifier() {
    return new DefaultGreetingService();
}

With this bean definition, DefaultGreetingService can be autowired using both qualifiedGreetingService and serviceWithQualifier - the method name.

Let's see the client code:

@Component
public class GreetingClient {

    @Autowired
    @Qualifier("qualifiedGreetingService")
    private GreetingService service4;

    @Autowired
    @Qualifier("serviceWithQualifier")
    private GreetingService service5;
}

One caveat to keep in mind, however: Although Spring resolves the bean correctly with qualifiedGreetingService, it doesn't register the DefaultGreetingService bean with the given name:

@Test
public void testBeanRegistration_WithQualifierAnnotation() {
    assertThat(context.containsBean("serviceWithQualifier")).isTrue();
    
    assertThat(context.containsBean("qualifiedGreetingService")).isFalse();
}

Here, context.containsBean("qualifiedGreetingService") returns false. This implies that we can autowire the bean using its @Qualifier name, but we can't retrieve it directly from the context.

6. Summary

In this tutorial, we've looked at how we can define Spring bean names using the @Bean annotation.

Check out the source code for all examples over on Github.