@Primary
由于按类型自动装配可能会导致多个候选对象,因此通常有必要更好地控制选择过程。一种实现此目的的方法是使用Spring的 @Primary注释。
@Primary指示当多个bean是要自动装配到单值依赖项的候选对象时,应给予特定bean优先权。如果候选对象中仅存在一个主bean,则它将成为自动装配的值。
考虑以下定义firstMovieCatalog为主要配置的配置MovieCatalog:
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... }
@Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
使用前面的配置,以下内容MovieRecommender将自动连接到 firstMovieCatalog:
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
// ...
}
限定符 @Qualifier
当您需要对选择过程进行更多控制时,可以使用Spring的@Qualifier注释。您可以将限定符值与特定的参数相关联,从而缩小类型匹配的范围,以便为每个参数选择特定的bean。在最简单的情况下,这可以是简单的描述性值,如以下示例所示:
public class MovieRecommender {
@Autowired
@Qualifier("main")
private MovieCatalog movieCatalog;
// ...
}
您还可以@Qualifier在各个构造函数参数或方法参数上指定注释,如以下示例所示:
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(@Qualifier("main") MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
以下示例显示了相应的bean定义。
<?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">
<qualifier value="main"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier value="action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
对于后备匹配,bean名称被认为是默认的限定符值。因此,可以使用idof main而不是嵌套的限定符元素来定义bean ,从而得到相同的匹配结果。但是,尽管您可以使用此约定按名称引用特定的bean,但从@Autowired根本上讲,它是带有可选语义限定符的类型驱动的注入。这意味着,即使带有Bean名称后退的限定符值,在类型匹配集中也始终具有狭窄的语义。它们没有在语义上表示对唯一bean的引用id。好的限定符值是main 或EMEA或persistent,表示独立于Bean的特定组件的特征id,如果是匿名bean定义(例如前面的示例中的定义),则可以自动生成。
限定词也适用于类型化的集合,如前所述(例如,) Set<MovieCatalog>。在这种情况下,根据声明的限定符,将所有匹配的bean作为集合注入。这意味着限定词不必是唯一的。相反,它们构成了过滤标准。例如,您可以定义MovieCatalog具有相同限定符值“ action”的多个bean,所有这些都将注入到带Set<MovieCatalog>注释的中@Qualifier("action")。
在类型匹配的候选对象中,让限定符值针对目标Bean名称进行选择,不需要@Qualifier在注入点处进行注释。如果没有其他解析度指示符(例如限定词或主标记),则对于非唯一依赖性情况,Spring将注入点名称(即字段名称或参数名称)与目标Bean名称进行匹配,然后选择同名候选人(如果有)。
您可以创建自己的自定义限定符注释。为此,请定义一个注释并@Qualifier在您的定义中提供该注释,如以下示例所示:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {
String value();
}
然后,您可以在自动连接的字段和参数上提供自定义限定符,如以下示例所示:
public class MovieRecommender {
@Autowired
@Genre("Action")
private MovieCatalog actionCatalog;
private MovieCatalog comedyCatalog;
@Autowired
public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) {
this.comedyCatalog = comedyCatalog;
}
// ...
}
接下来,您可以提供有关候选bean定义的信息。您可以将<qualifier/>标签添加为 标签的子元素,<bean/>然后指定type和 value以匹配您的自定义限定符注释。该类型与注释的标准类名匹配。另外,为方便起见,如果不存在名称冲突的风险,则可以使用简短的类名。
<?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">
<qualifier type="Genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier type="example.Genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
网友评论