关于 Spring 注解容器配置的那些事,掌握这几点,不再难( 二 )

从 Spring 框架 4.3 起 , 如果目标 bena 仅定义了一个构造函数 , 那么@Autowired注解的构造函数不再是必要的 。如果一些构造函数是可获得的 , 至少有一个必须要加上注解 , 以便于告诉容器使用哪一个 。
 
正如预料的那样 , 你也可以将@Autowired注解应用到“传统的”setter 方法上:
public class SimpleMovieLister {private MovieFinder movieFinder;@Autowiredpublic void setMovieFinder(MovieFinder movieFinder) {this.movieFinder = movieFinder;}// ...}你也可以应用注解到具有任何名字和/或多个参数的方法上:
public class MovieRecommender {private MovieCatalog movieCatalog;private CustomerPreferenceDao customerPreferenceDao;@Autowiredpublic void prepare(MovieCatalog movieCatalog,CustomerPreferenceDao customerPreferenceDao) {this.movieCatalog = movieCatalog;this.customerPreferenceDao = customerPreferenceDao;}// ...}你也可以应用@Autowired到字段上 , 甚至可以与构造函数混合用:
public class MovieRecommender {private final CustomerPreferenceDao customerPreferenceDao;@Autowiredprivate MovieCatalog movieCatalog;@Autowiredpublic MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {this.customerPreferenceDao = customerPreferenceDao;}// ...}通过给带有数组的字段或方法添加@Autowired注解 , 也可以从ApplicationContext中提供一组特定类型的 bean:
public class MovieRecommender {@Autowiredprivate MovieCatalog[] movieCatalogs;// ...}同样也可以应用到具有同一类型的集合上:
public class MovieRecommender {private Set<MovieCatalog> movieCatalogs;@Autowiredpublic void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {this.movieCatalogs = movieCatalogs;}// ...}
如果你希望数组或列表中的项按指定顺序排序 , 你的 bean 可以实现
org.springframework.core.Ordered接口 , 或使用@Order或标准@Priority注解 。
 
只要期望的 key 是String , 那么类型化的 Maps 就可以自动组装 。Map 的值将包含所有期望类型的 beans , key 将包含对应的 bean 名字:
public class MovieRecommender {private Map<String, MovieCatalog> movieCatalogs;@Autowiredpublic void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {this.movieCatalogs = movieCatalogs;}// ...}默认情况下 , 当没有候选 beans 可获得时 , 自动组装会失败;默认的行为是将注解的方法 , 构造函数和字段看作指明了需要的依赖 。这个行为也可以通过下面的方式去改变 。
public class SimpleMovieLister {private MovieFinder movieFinder;@Autowired(required=false)public void setMovieFinder(MovieFinder movieFinder) {this.movieFinder = movieFinder;}// ...}
每个类只有一个构造函数可以标记为必需的 , 但可以注解多个非必需的构造函数 。在这种情况下 , 会考虑这些候选者中的每一个 , Spring 使用最贪婪的构造函数 , 即依赖最满足的构造函数 , 具有最大数目的参数 。
 
建议在@Required注解之上使用@Autowired的required特性 。required特性表明这个属性自动装配是不需要的 , 如果这个属性不能被自动装配 , 它会被忽略 。另一方面@Required是更强大的 , 在它强制这个属性被任何容器支持的 bean 设置 。如果没有值注入 , 会抛出对应的异常 。
 
你也可以对那些已知的具有可解析依赖的接口使用@Autowired:BeanFactory , ApplicationContext , Environment, ResourceLoader , ApplicationEventPublisher和MessageSource 。这些接口和它们的扩展接口 , 例如
ConfigurableApplicationContext或ResourcePatternResolver , 可以自动解析 , 不需要特别的设置 。
public class MovieRecommender {@Autowiredprivate ApplicationContext context;public MovieRecommender() {}// ...}@Autowired、@Inject、@Resource和@Value都是通过 Spring 的BeanPostProcessor实现处理的 , 这反过来意味着 , 你不能在自己的BeanPostProcessor或BeanFactoryPostProcessor中使用这些注解 。
 
这些类型必须显式通过 XML 或使用 Spring 的@Bean方法来装配 。
3 用 @Primary 微调基于注解的自动装配
因为根据类型的自动装配可能会导致多个候选目标 , 所以在选择过程中进行更多的控制经常是有必要的 。一种方式通过 Spring 的@Primary注解来完成 。当有个多个候选 bean 要组装到一个单值的依赖时 , @Primary表明指定的 bean 应该具有更高的优先级 。如果确定一个’primary’ bean 位于候选目标中间 , 它将是那个自动装配的值 。


推荐阅读