When developing with Spring Boot, you’ll often find yourself using @Bean. And one question that quietly trips people up is: “Should I give this @Bean a name, or just leave it?”

This article takes a practical look at what Bean names are used for, when you should specify them explicitly, and how Spring decides which Bean gets chosen when multiple candidates exist.

What Is a @Bean “Name”?

In Spring, every Bean registered in the container has a “Bean name (identifier).” For @Bean, this name shows up primarily in the following situations:

  • Determining which Bean to inject when multiple Beans of the same type exist
  • Name-based injection via @Qualifier / @Resource, etc.
  • Conditional Bean registration (e.g., @ConditionalOnBean(name=...))
  • Bean overriding and collision detection

In short, the name is the key used to identify a Bean.

Default Naming Rules

When you don’t specify a name on @Bean, the Bean name defaults to the method name.

@Configuration
public class MyConfig {

    @Bean
    public MyService myService() {
        return new MyService();
    }
}

In this example, the Bean name is myService.

Method name = Bean name — it’s a simple rule, but worth keeping in mind: even if you think you haven’t given a Bean a name, it already has one.

How to Set Names (Explicit Names & Aliases)

Assigning a Single Name

@Configuration
public class MyConfig {

    @Bean("mainService")
    public MyService myService() {
        return new MyService();
    }
}

@Bean("...") is shorthand and is equivalent to @Bean(name="...").

Assigning Aliases

You can give a single Bean multiple names:

@Configuration
public class MyConfig {

    @Bean({"dataSource", "readDataSource"})
    public DataSource dataSource() {
        // ...
        return /* DataSource */;
    }
}

In this case, the same Bean can be referenced by either dataSource or readDataSource. (That said, overusing aliases makes code harder to read — use only when necessary.)

When Should You Assign a Name?

The short answer: in most cases, leaving it unnamed (i.e., using the method name) is fine. However, there are situations where explicitly naming a Bean pays off:

When You Have Multiple @Beans of the Same Type

For example, when you need two variations of MyClient:

@Configuration
public class ClientConfig {

    @Bean("userClient")
    public MyClient userClient() {
        return new MyClient("https://user-api.example");
    }

    @Bean("billingClient")
    public MyClient billingClient() {
        return new MyClient("https://billing-api.example");
    }
}

When Beans of the same type serve different purposes, naming them to convey intent makes future maintenance easier. (The method name alone could work, but if you plan to use @Qualifier, explicit names make the intent clearer.)

When You Want to Specify the Bean at the Injection Site via @Qualifier / @Resource

As discussed below, names are a powerful tool for resolving injection targets. If you have a firm intent — “this injection point must use this Bean” — giving it a name is the safe choice.

When You Want to Reference a Bean Name in a Condition

Spring Boot’s auto-configuration and custom conditional logic sometimes rely on Bean names:

  • @ConditionalOnBean(name = "xxx")
  • @ConditionalOnMissingBean(name = "xxx")

When the name becomes part of your API, making it explicit is the safer approach.

When You Need to Distinguish Your Bean from One Provided by an External Library

Sometimes you define your own Bean of the same type as one provided by an external library. In these cases, giving them distinct names keeps injection readable.

Injection Priority (@Qualifier / @Primary / Parameter Name, etc.)

This is the most nuanced part. The key question is: after Spring collects candidates by type, how does it narrow down to one?

The Basics: @Autowired Starts with “Type”

@Service
public class MyUseCase {

    private final MyClient client;

    public MyUseCase(MyClient client) {
        this.client = client;
    }
}

If there’s only one MyClient Bean, this resolves cleanly. But if multiple exist, Spring can’t decide and throws an error.

@Qualifier Takes Highest Priority (the Strongest Tool in Practice)

@Service
public class MyUseCase {

    private final MyClient client;

    public MyUseCase(@Qualifier("billingClient") MyClient client) {
        this.client = client;
    }
}

@Qualifier("billingClient") narrows the candidates down precisely. No matter how many Beans of the same type exist, you can target a specific one by name (or Qualifier).

@Primary Is Useful When You Want to Define a “Default” Bean

@Configuration
public class ClientConfig {

    @Bean
    @Primary
    public MyClient primaryClient() {
        return new MyClient("https://default.example");
    }

    @Bean("billingClient")
    public MyClient billingClient() {
        return new MyClient("https://billing-api.example");
    }
}

@Primary declares: “if there are multiple candidates, use this one by default.” However, if the injection site specifies @Qualifier, that takes precedence over @Primary. (This enables a clean pattern: “use the default unless a specific Bean is explicitly requested.”)

Parameter Names Can Sometimes Serve as a Hint

When multiple Beans of the same type exist, Spring may resolve the injection by matching the field name or parameter name against a Bean name:

@Service
public class MyUseCase {

    private final MyClient billingClient;

    public MyUseCase(MyClient billingClient) {
        this.billingClient = billingClient;
    }
}

If a Bean named billingClient exists, this may resolve correctly. However, this depends on compiler settings and other factors, so in practice, using @Qualifier explicitly is the safer and more reliable approach.

@Resource Resolves by Name First

@Resource resolves by name rather than by type:

@Service
public class MyUseCase {

    @Resource(name = "billingClient")
    private MyClient client;
}

The behavior differs from @Autowired, so mixing both can cause confusion. (If you use @Resource, treat it as “name-based injection” and use it consistently.)

Bean Name Collisions and Override Warnings

Bean names must be unique. If multiple Bean definitions share the same name, Spring Boot will raise an error by default (overriding is disabled by default).

For example, defining a method with the same name in two different configuration classes causes a collision:

@Configuration
public class AConfig {
    @Bean
    public MyService myService() { return new MyService(); }
}

@Configuration
public class BConfig {
    @Bean
    public MyService myService() { return new MyService(); }
}

The collision is based on the name, not the type — so this will blow up at startup.

The simplest way to avoid this: if the intent is different, give them different names (or method names).

Note

Tip: Consider Defining Bean Names as Constants

Hardcoding strings like @Qualifier("billingClient") is prone to typos and breakage during renames. In practice, defining Bean names as constants and referencing them is the safer approach:

public final class BeanNames {
    private BeanNames() {}

    public static final String BILLING_CLIENT = "billingClient";
    public static final String USER_CLIENT = "userClient";
}
@Configuration
public class ClientConfig {

    @Bean(BeanNames.USER_CLIENT)
    public MyClient userClient() {
        return new MyClient("https://user-api.example");
    }

    @Bean(BeanNames.BILLING_CLIENT)
    public MyClient billingClient() {
        return new MyClient("https://billing-api.example");
    }
}
@Service
public class MyUseCase {

    private final MyClient client;

    public MyUseCase(@Qualifier(BeanNames.BILLING_CLIENT) MyClient client) {
        this.client = client;
    }
}

This way, if a Bean name ever needs to change, the fix is isolated to a single location — the constant definition.

Summary

  • The default Bean name for @Bean is the method name
  • Typical cases for explicit naming: multiple Beans of the same type, name-based injection, name-referenced conditions
  • Injection priority, roughly speaking:
    • @Qualifier — strongest, explicit targeting
    • @Primary — sets the default when multiple candidates exist
    • Name matching — parameter/field name may resolve the ambiguity
  • Duplicate Bean names cause startup errors in Spring Boot — watch out for name collisions

@Bean names fly under the radar in everyday development, but the moment multiple Beans of the same type appear, they become critically important.

When in doubt, anchor your design around these three rules:

  • Use @Primary as the default
  • Use @Qualifier where explicit targeting is needed
  • Avoid hardcoded strings — define names as constants