Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 955
user Avatar asked Nov 26 '18 14:11

user


People also ask

Can we create 2 beans of same class?

2. Using Java Configuration. This is the simplest and easiest way to create multiple beans of the same class using annotations. In this approach, we'll use a Java-based configuration class to configure multiple beans of the same class.

Can we use @primary and @qualifier together?

We can use @Qualifier and @Primary for the same bean. Use @Qualifier to inject specific bean otherwise Spring injects bean by default which is annotated with @Primary.

Can we have two bean of same type in Spring?

When the Spring context contains multiple beans of the same type, Spring selects the bean whose name matches the name of the parameter. As we discussed for the parameter of the @Bean annotated method, I recommend avoiding relying on the name of the variable.

Can we use @qualifier and @bean together?

NOTE: if you are creating bean with @Bean, it will be injected byType if there is duplicates then it will injected byName. we no need to mention @Bean(name="bmwDriver") . so you can directly use qualifier("bmwDriver") wherever you need in classes.


2 Answers

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) { /*...*/ } 
}
like image 53
Michael Avatar answered Oct 13 '22 12:10

Michael


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.

like image 27
cнŝdk Avatar answered Oct 13 '22 12:10

cнŝdk