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.
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.
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.
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.
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.
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 MyType
s. In which case, both beans would be autowired.
@Component
class AnotherComponent
{
public AnotherComponent(List<MyType> allFoos) { /*...*/ }
}
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With