user
user

Reputation: 4830

Why can I create another bean if a @Primary bean exists?

I don't understand what problem @Primary resolves.

The documentation says:

[@Primary] Indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency. If exactly one 'primary' bean exists among the candidates, it will be the autowired value.

Example code:

@Configuration
class Configuration {
   @Bean
   @Primary
   MyType bean1() {
       return new MyType(1);
   }

   @Bean
   MyType bean2() {
       return new MyType(2);
   }
}

Example:

I have 2 beans, bean1 and bean2, both with the type MyType. bean1 has a @Primary annotation, so when I autowire an object of type MyType to some constructor, bean1 will be chosen.

Why is it useful to have two beans of the same type if the primary bean will always be chosen? When and how could I use bean2 which isn't annotated as primary? The example shows that bean2 is redundant and unused.

Upvotes: 17

Views: 21852

Answers (4)

Michael
Michael

Reputation: 44150

You can still always qualify which bean you actually want, meaning the primary one will not always be chosen.

@Component
class MyComponent
{
    public MyComponent(@Qualifier("bean2") MyType foo) { /*...*/ } 
}

@Primary just tells Spring which bean to give precedence to if there are two or more possible candidates. You can always be explicit.

Also, another constructor might take a list of all MyTypes. In which case, both beans would be autowired.

@Component
class AnotherComponent
{
    public AnotherComponent(List<MyType> allFoos) { /*...*/ } 
}

Upvotes: 9

greene
greene

Reputation: 672

One of possible usages of @Primary you can override your Bean in tests by set @Primary there. Still your secondary Bean is used when you run an application.

Upvotes: 0

cнŝdk
cнŝdk

Reputation: 32145

So why could I have two beans of the same type if primary bean will be injected?

Actually the primary bean will be only injected if you didn't specify which one of your beans you want to inject, and @Primary is used to specify which bean will be injected when the type is not specified.

And to answer your question, having two beans of the same type is a common way of giving different implementations, there are many cases when we want to use two beans of the same bean, the most common situation is when we want to specify two data sources for the same application.

And to specify which one of our beans we want to go with, we use the @Resource annotation like this:

@Resource(name="bean2")
MyType bean;

For futher details you can check the discussed differences between @Resource and @Autowired.

Upvotes: 3

NiVeR
NiVeR

Reputation: 9786

Say you have multiple instances of beans which have some differences among them. In many cases (say > 90% for example) you will need one of them, and you will rarely use the other ones. In this case it makes sense to annotate as @Primary the most used one and in this way it will be directly injected by the framework when no further specification is provided. In the other case you will specify the exact bean to use using the @Qualifier annotation.

An example can be initializing beans of RestTemplate, say you will define a global one which will have generic settings and will be used accross all application, and another one with some specific retry policy for a small set of use-cases.

Upvotes: 1

Related Questions