Here's the class with the primary bean:
@Configuration
public class AppConfig {
@Bean
@Primary
public WeatherGauge weatherGauge() {
return () -> "40 F";
}
}
and here's the class defining and using the competing bean:
@Configuration
public class WeatherConfig {
@Bean
public WeatherGauge weatherGauge() {
return () -> "20 C";
}
@Bean
public StateReporter stateReporter(WeatherGauge weatherGauge) {
return new StateReporter(weatherGauge);
}
}
I'm using spring-boot-starter-parent:2.1.9.RELEASE
. If I use StateReporter
and print the weather gauge, I get 20 C, which does not come from the primary bean. The @Primary
is ignored. Is this by design or a flaw? Just the way @Configuration
works? If I define the primary implementation as a @Component
class, the @Primary
is in fact honored.
Edit: I forgot to say that AppConfig
gets picked up if the other bean is not present. Everything is in the same package as the main class and I do use the allow-override=true
property.
You're defining two beans with the same name and type: only one will be created, and the other will be overridden.
The @Primary
annotation is for when two or more beans of the same type exist. It designates one of them as the primary bean used in dependency injection.
You can see how this works by making a small code change.
@Bean
@Primary
public WeatherGauge weatherGauge2() {
return new WeatherGauge("40 F");
}
@Bean
public WeatherGauge weatherGauge() {
return new WeatherGauge("20 C");
}
Now two beans are defined, with one of them weatherGauge2
being the primary.
I assumed that you used the prop:
spring.main.allow-bean-definition-overriding=true
to run this code. This link probably will clear your problem for you.
If you don't want to read the whole article:
The mechanism which caused you this problem is called bean overriding. It's almost impossible to predict which bean will override another with Java-based configs. When you use both (XML and Java based) configurations, then Java-based is always loaded first and XML configuration always latest, so it will override everything else. That's why your @Component
class with @Primary
is honored - because it is loaded after configuration.
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