@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定义。
对于后备匹配,bean名称被认为是默认的限定符值。因此,可以使用idof main而不是嵌套的限定符元素来定义bean ,从而得到相同的匹配结果。但是,尽管您可以使用此约定按名称引用特定的bean,但从@Autowired根本上讲,它是带有可选语义限定符的类型驱动的注入。这意味着,即使带有Bean名称后退的限定符值,在类型匹配集中也始终具有狭窄的语义。它们没有在语义上表示对唯一bean的引用id。好的限定符值是main 或EMEA或persistent,表示独立于Bean的特定组件的特征id,如果是匿名bean定义(例如前面的示例中的定义),则可以自动生成。
限定词也适用于类型化的集合,如前所述(例如,) Set
在类型匹配的候选对象中,让限定符值针对目标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定义的信息。您可以将