Spring注入还可以这样玩!涨知识了

假设你有两个 CommonDAO bean,每个都需要在不同的环境中使用 。这时,你可以使用 @Qualifier 来指定具体的 bean 。环境:Spring6.1.2
1. 简介@Qualifier是 Spring 框架中的一个注解,它用于消除自动装配(autowiring)时的歧义 。在 Spring 应用程序中,当存在多个相同类型的 bean 时 , 自动装配可能会产生歧义,因为 Spring 容器不知道该选择哪个 bean 进行注入 。这时,我们可以使用 @Qualifier 注解来明确指定要注入的 bean 。
假设你有两个 CommonDAO bean,每个都需要在不同的环境中使用 。这时 , 你可以使用 @Qualifier 来指定具体的 bean 。
public class CommonService {@Resource@Qualifierprivate CommonDAO dao ;}@Configurationpublic class AppConfig {@Bean@Qualifierpublic TeacherDAO teacherDAO() {return new TeacherDAO() ;}@Beanpublic StudentDAO studentDAO() {return new StudentDAO() ;}@Beanpublic CommonService commonService() {return new CommonService() ;}}上面示例中如果注入的CommonDAO字段上没有添加@Qualifier注解,那么程序将会报错 , 这里通过@Qualifier注解来限定注入的值;该注解也可以设置value属性 。
2. 更多玩法上面直接通过使用@Qualifier注解来限定注入值,接下来将介绍其它的使用方法 。
2.1 自定义限定注解@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Qualifierpublic @interface Pack {String value();}自定义限定注解 , 该注解上使用了@Qualifier注解 。接下来我们就可以使用该注解 。
public class CommonService {@Resource@Packprivate CommonDAO dao ;}@Bean@Packpublic TeacherDAO teacherDAO() {return new TeacherDAO() ;}这时候你就可以自定义不同的注解分别标准你要注入的值 。
2.2 泛型限定注入有如下接口定义,该接口是泛型接口:
public class Teacher {}public class Student {}public interface CommonDAO<T> {}public class TeacherDAO implements CommonDAO<Teacher> {}public class StudentDAO implements CommonDAO<Student> {}public class CommonService {@Resourceprivate CommonDAO<Student> dao ;@Overridepublic String toString() {return "CommonService [dao=" + dao + "]";}}在上面CommonDAO的注入中如果你泛型使用的Student那么注入的将是StudentDAO,如果是Teacher类型,那么注入的将是TeacherDAO 。
泛型限定符也可用于List、Map 实例和数组 。如下使用List示例:
@Resourceprivate List<CommonDAO<Student>> daos ;这将注入容器中所有泛型是Student类型的CommonDAO实例对象 。
2.3 完全自定义注解有如下注解,我们完全可以不依赖任何Spring相关的注解实现限定的注入值 。
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface Pack {String value() default "" ;}该自定义注解并没有使用Spring的@Qualifier注解 。要使得上面注解生效你还需要配置如下类:
@Beanpublic CustomAutowireConfigurer customAutowireConfigurer() {CustomAutowireConfigurer autowireConfigurer = new CustomAutowireConfigurer() ;// 指定我们自定义的注解autowireConfigurer.setCustomQualifierTypes(Set.of(Pack.class)) ;return autowireConfigurer ;}CustomAutowireConfigurer是BeanFactoryPostProcessor,这会帮助我们注册自定义的限定注解 。
2.4 更多属性控制除了上面的方式限定注入的值,我们还可以自定义注解,指定更多的属性值去匹配bean对象,只有bean对象具有相同的属性值(元数据信息)才能匹配 。
public enum Format {JSON, CSV, PLAIN}@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Qualifierpublic @interface Pack {String value() default "" ;// 指定格式Format format() ;}// Bean定义指定每一种bean对应的格式format@Pack(format = Format.CSV)public class CSVDAO implements CommonDAO {}@Pack(format = Format.JSON)public class JSONDAO implements CommonDAO {}接下来在注册上面两个*DAO bean时就不能通过注解的方式了,只能通过xml或者BeanDefinition的方式注册,如下示例:
ApplicationContext context = ... ;// 分别设置他们的元数据信息 。context.registerBean(CSVDAO.class, bd -> {bd.setAttribute("format", "CSV") ;});context.registerBean(JSONDAO.class, bd -> {bd.setAttribute("format", "JSON") ;});注入配置:
@Resource@Pack(format = Format.JSON)private CommonDAO dao ;通过上面指定format属性,以确定需要注入对象的明确要求 。

【Spring注入还可以这样玩!涨知识了】


推荐阅读