diff --git a/framework-docs/modules/ROOT/pages/core/beans/annotation-config/autowired-qualifiers.adoc b/framework-docs/modules/ROOT/pages/core/beans/annotation-config/autowired-qualifiers.adoc index 1758ca42d76..d8c24257da2 100644 --- a/framework-docs/modules/ROOT/pages/core/beans/annotation-config/autowired-qualifiers.adoc +++ b/framework-docs/modules/ROOT/pages/core/beans/annotation-config/autowired-qualifiers.adoc @@ -151,17 +151,17 @@ injected into a `Set` annotated with `@Qualifier("action")`. [TIP] ==== Letting qualifier values select against target bean names, within the type-matching -candidates, does not require a `@Qualifier` annotation at the injection point. -If there is no other resolution indicator (such as a qualifier or a primary marker), -for a non-unique dependency situation, Spring matches the injection point name -(that is, the field name or parameter name) against the target bean names and chooses -the same-named candidate, if any (either by bean name or by associated alias). +candidates, does not require a `@Qualifier` annotation at the injection point. If there +is no other resolution indicator (such as a qualifier, a primary marker, or a fallback +marker), for a non-unique dependency situation, Spring matches the injection point name +(that is, the field name or parameter name) against the target bean names and chooses the +same-named candidate, if any (either by bean name or by associated alias). -Since version 6.1, this requires the `-parameters` Java compiler flag to be present. -As of 6.2, the container applies fast shortcut resolution for bean name matches, -bypassing the full type matching algorithm when the parameter name matches the -bean name and no type, qualifier or primary conditions override the match. It is -therefore recommendable for your parameter names to match the target bean names. +Since version 6.1, this requires the `-parameters` Java compiler flag to be present. As +of 6.2, the container applies fast shortcut resolution for bean name matches, bypassing +the full type matching algorithm when the parameter name matches the bean name and no +type, qualifier, primary, or fallback conditions override the match. It is therefore +recommendable for your parameter names to match the target bean names. ==== As an alternative for injection by name, consider the JSR-250 `@Resource` annotation diff --git a/framework-docs/modules/ROOT/pages/core/beans/annotation-config/autowired.adoc b/framework-docs/modules/ROOT/pages/core/beans/annotation-config/autowired.adoc index a821a5b8a69..b24beb12e5a 100644 --- a/framework-docs/modules/ROOT/pages/core/beans/annotation-config/autowired.adoc +++ b/framework-docs/modules/ROOT/pages/core/beans/annotation-config/autowired.adoc @@ -309,7 +309,8 @@ set of multiple matches for the specific bean type (as returned by the factory m Note that the standard `jakarta.annotation.Priority` annotation is not available at the `@Bean` level, since it cannot be declared on methods. Its semantics can be modeled -through `@Order` values in combination with `@Primary` on a single bean for each type. +through `@Order` values in combination with `@Primary` or `@Fallback` on a single bean +for each type. ==== Even typed `Map` instances can be autowired as long as the expected key type is `String`. diff --git a/framework-docs/modules/ROOT/pages/core/beans/annotation-config/custom-autowire-configurer.adoc b/framework-docs/modules/ROOT/pages/core/beans/annotation-config/custom-autowire-configurer.adoc index 2c7fc82da4c..1a2e5410bb4 100644 --- a/framework-docs/modules/ROOT/pages/core/beans/annotation-config/custom-autowire-configurer.adoc +++ b/framework-docs/modules/ROOT/pages/core/beans/annotation-config/custom-autowire-configurer.adoc @@ -27,4 +27,5 @@ with the `CustomAutowireConfigurer` When multiple beans qualify as autowire candidates, the determination of a "`primary`" is as follows: If exactly one bean definition among the candidates has a `primary` -attribute set to `true`, it is selected. +attribute set to `true`, it is selected. For annotation-based configuration, see +xref:core/beans/annotation-config/autowired-primary.adoc[Fine-tuning with `@Primary` or `@Fallback`]. diff --git a/framework-docs/modules/ROOT/pages/web/webflux/config.adoc b/framework-docs/modules/ROOT/pages/web/webflux/config.adoc index 780fb943408..9c255395a73 100644 --- a/framework-docs/modules/ROOT/pages/web/webflux/config.adoc +++ b/framework-docs/modules/ROOT/pages/web/webflux/config.adoc @@ -251,7 +251,8 @@ Kotlin:: ====== TIP: If you need to have a `LocalValidatorFactoryBean` injected somewhere, create a bean and -mark it with `@Primary` in order to avoid conflict with the one declared in the MVC config. +mark it with `@Primary`, or mark the one declared in the MVC config with `@Fallback`, in +order to avoid conflict. [[webflux-config-content-negotiation]] diff --git a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-config/validation.adoc b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-config/validation.adoc index bdf891578dd..5597e5c38f4 100644 --- a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-config/validation.adoc +++ b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-config/validation.adoc @@ -19,4 +19,5 @@ example shows: include-code::./MyController[tag=snippet,indent=0] TIP: If you need to have a `LocalValidatorFactoryBean` injected somewhere, create a bean and -mark it with `@Primary` in order to avoid conflict with the one declared in the MVC configuration. +mark it with `@Primary`, or mark the one declared in the MVC configuration with +`@Fallback`, in order to avoid conflict. diff --git a/spring-context/src/main/java/org/springframework/context/annotation/Bean.java b/spring-context/src/main/java/org/springframework/context/annotation/Bean.java index e5d1d058096..c996c5d740e 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/Bean.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/Bean.java @@ -57,11 +57,11 @@ import org.springframework.core.annotation.AliasFor; * return obj; * } * - *

Profile, Scope, Lazy, DependsOn, Primary, Order

+ *

Profile, Scope, Lazy, DependsOn, Primary, Fallback, Order

* *

Note that the {@code @Bean} annotation does not provide attributes for profile, - * scope, lazy, depends-on or primary. Rather, it should be used in conjunction with - * {@link Scope @Scope}, {@link Lazy @Lazy}, {@link DependsOn @DependsOn} and + * scope, lazy, depends-on, or primary. Rather, it should be used in conjunction with + * {@link Scope @Scope}, {@link Lazy @Lazy}, {@link DependsOn @DependsOn}, and * {@link Primary @Primary} annotations to declare those semantics. For example: * *

@@ -82,6 +82,9 @@ import org.springframework.core.annotation.AliasFor;
  * through direct references, which is typically helpful for singleton startup.
  * {@code @Primary} is a mechanism to resolve ambiguity at the injection point level
  * if a single target component needs to be injected but several beans match by type.
+ * {@code @Fallback} marks a bean as a fallback candidate in such scenarios; if all
+ * beans but one among multiple matching candidates are marked as fallback, the
+ * remaining bean will be selected.
  *
  * 

Additionally, {@code @Bean} methods may also declare qualifier annotations * and {@link org.springframework.core.annotation.Order @Order} values, to be @@ -97,8 +100,8 @@ import org.springframework.core.annotation.AliasFor; * orthogonal concern determined by dependency relationships and {@code @DependsOn} * declarations as mentioned above. Also, {@link jakarta.annotation.Priority} is not * available at this level since it cannot be declared on methods; its semantics can - * be modeled through {@code @Order} values in combination with {@code @Primary} on - * a single bean per type. + * be modeled through {@code @Order} values in combination with {@code @Primary} or + * {@code @Fallback} on a single bean per type. * *

{@code @Bean} Methods in {@code @Configuration} Classes

* @@ -230,6 +233,7 @@ import org.springframework.core.annotation.AliasFor; * @see DependsOn * @see Lazy * @see Primary + * @see Fallback * @see org.springframework.stereotype.Component * @see org.springframework.beans.factory.annotation.Autowired * @see org.springframework.beans.factory.annotation.Value