Fine-tuning Annotation-based Autowiring with @Primary
or @Fallback
由于按类型自动装配可能导致出现多个候选对象,因此通常需要对选择过程进行更多控制。一种实现此目的的方法是使用 Spring 的 @Primary
注解。@Primary
指示当多个 Bean 是要自动装配到单值依赖项的候选对象时,应优先考虑特定的 Bean。如果候选对象中恰好只有一个主要 Bean,则它将成为自动装配的值。
Because autowiring by type may lead to multiple candidates, it is often necessary to have
more control over the selection process. One way to accomplish this is with Spring’s
@Primary
annotation. @Primary
indicates that a particular bean should be given
preference when multiple beans are candidates to be autowired to a single-valued
dependency. If exactly one primary bean exists among the candidates, it becomes the
autowired value.
考虑将 firstMovieCatalog
定义为主要 MovieCatalog
的以下配置:
Consider the following configuration that defines firstMovieCatalog
as the
primary MovieCatalog
:
-
Java
-
Kotlin
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... }
@Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
@Configuration
class MovieConfiguration {
@Bean
@Primary
fun firstMovieCatalog(): MovieCatalog { ... }
@Bean
fun secondMovieCatalog(): MovieCatalog { ... }
// ...
}
或者,从 6.2 开始,有一个 @Fallback
注解,用于划分要注入的除常规 Bean 之外的任何 Bean。如果只保留了一个常规 Bean,则它实际上也是主要 Bean:
Alternatively, as of 6.2, there is a @Fallback
annotation for demarcating
any beans other than the regular ones to be injected. If only one regular
bean is left, it is effectively primary as well:
-
Java
-
Kotlin
@Configuration
public class MovieConfiguration {
@Bean
public MovieCatalog firstMovieCatalog() { ... }
@Bean
@Fallback
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
@Configuration
class MovieConfiguration {
@Bean
fun firstMovieCatalog(): MovieCatalog { ... }
@Bean
@Fallback
fun secondMovieCatalog(): MovieCatalog { ... }
// ...
}
使用前述配置的两个变体,以下 MovieRecommender
将使用 firstMovieCatalog
自动装配:
With both variants of the preceding configuration, the following
MovieRecommender
is autowired with the firstMovieCatalog
:
-
Java
-
Kotlin
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
// ...
}
class MovieRecommender {
@Autowired
private lateinit var movieCatalog: MovieCatalog
// ...
}
相应的 Bean 定义如下:
The corresponding bean definitions follow:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog" primary="true">
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>