在spring中,提供了@Qualifier
注解,帮助我们精确的注入需要的bean实例。这边文章主要介绍该注解在spring开发中的两种使用方式,能够帮助我们优雅的实现代码。
首先开始学习时,先查看下该注解的源码,以及注解方式,然后再以demo的方式实现。
@Qualifier源码
/** * This annotation may be used on a field or parameter as a qualifier for * candidate beans when autowiring. It may also be used to annotate other * custom annotations that can then in turn be used as qualifiers. * * @author Mark Fisher * @author Juergen Hoeller * @since 2.5 * @see Autowired */ @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Qualifier { String value() default ""; }
通过源码注解可以得知, 该注解使用有两种场景:
- 通过配合
@Autowired
注解实现精准bean注入 - 自动注解,然后将自定义注解上加入
@Qualifier
注解,派生出新的注解
DEMO实现
接下来将通过代码的方式演示以上两种使用方式,下面我们通过定义配置类型,生成我们需要bean对象. 具体代码如下:
import org.spring.learn.eureka.client.annotation.MyQualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author xianglujun * @date 2021/9/17 11:06 * @since */ @Configuration public class MyQualifierConfiguration { public class BaseService { } @MyQualifier @Bean public BaseService baseService() { return new BaseService(); } @Bean public BaseService noQualifierBaseService() { return new BaseService(); } }
在以上代码中,我自定义一个注解@MyQualifier
, 该注解又被@Qualifier
注解。因此@MyQualifier
注解是@Qualifier
注解的一个派生。具体代码如下:
/** * @author xianglujun * @date 2021/9/17 11:04 * @since */ @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Qualifier public @interface MyQualifier { }
在configuration
的配置类中,我们创建了两个bean对象:
baseService
的bean, 该bean是被自定义注解@MyQualifier
修饰noQualifierBaseService
则是一个普通的bean对象,没有区别。
当以上类型配置完成之后,接下来我们验证这两个bean在使用上的差别,这里我们新建一个类型MyQualifierService
,具体源码如下:
import java.util.List; import javax.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import org.spring.learn.eureka.client.annotation.MyQualifier; import org.spring.learn.eureka.client.config.MyQualifierConfiguration.BaseService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; /** * @author xianglujun * @date 2021/9/17 11:09 * @since */ @Slf4j @Service public class MyQualifierService { @Autowired private List<BaseService> baseServices; @Qualifier("baseService") @Autowired private BaseService onlyOneService; @MyQualifier @Autowired private BaseService baseService; @PostConstruct public void init() { log.info("baseService: {}", baseServices); log.info("baseService: {}", baseService); } }
在这个类中包含了三个属性, 具体特点如下:
baseServices
: 在spring容器中查找所有BaserService
类型的bean对象onlyOneService
: 在spring容器中查找bean名称为baseService
的实例baseService
: 则是查找类型为BaseService并且被@MyQualifier
注解修饰的实例
我们将spring容器启动起来,并查看到日志内容如下:
2021-09-17 11:42:05.420 INFO 110960 --- [ main] o.s.l.e.c.service.MyQualifierService : onlyOneService: org.spring.learn.eureka.client.config.MyQualifierConfiguration$BaseService@4375b013 2021-09-17 11:42:05.422 INFO 110960 --- [ main] o.s.l.e.c.service.MyQualifierService : baseService: [org.spring.learn.eureka.client.config.MyQualifierConfiguration$BaseService@4375b013, org.spring.learn.eureka.client.config.MyQualifierConfiguration$BaseService@1cf0cacc] 2021-09-17 11:42:05.422 INFO 110960 --- [ main] o.s.l.e.c.service.MyQualifierService : baseService: org.spring.learn.eureka.client.config.MyQualifierConfiguration$BaseService@4375b013
可以看到,程序能够正常的执行,并且能够正常的将所依赖的实体注入。并且跟上面我们对程序执行的推断也是正确的。
总结
当我们在平日开发中, 我们可以利用派生注解的方式,避免@Qualifier("name")
这种硬代码注入bean. 所在在代码开发上,其实显得更加优雅一点吧。