当前位置: 代码迷 >> 综合 >> Spring中的Qualifier应用
  详细解决方案

Spring中的Qualifier应用

热度:14   发布时间:2024-03-06 17:09:41.0

应用

 

@Qualifier可以用来让程序员明确指定想要指定哪个bean,那有程序员就会想问,它和@Autowired和@Resource的区别是什么?

假设有如下bean定义:

    <bean id="user0" class="com.luban.entity.User"><property name="name" value="user0000"/></bean><bean id="user1" class="com.luban.entity.User" ><property name="name" value="user1111"/></bean><bean name="userService" class="com.luban.service.UserService" autowire="constructor"/>

user0和user1的类型都是user,

UserService的通过构造方法自动注入。

 

public class UserService {private User user;public UserService(User user11) {this.user = user11;}public void test() {System.out.println(user.getName());}
}

main方法:

    public static void main(String[] args) {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");UserService userService = applicationContext.getBean("userService", UserService.class);userService.test();}

 

现在运行main方法,会启动Spring,会报错:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.luban.entity.User' available: expected single matching bean but found 2: user0,user1at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:223)at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1324)at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1255)at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:939)at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:842)... 15 more

 

很明显,因为UserService会根据构造方法自动注入,会先根据构造方法参数类型User是找bean,找到了两个,一个user0, 一个user1,然后会根据构造方法参数名user11去进行过滤,但是过滤不出来,最终还是找到了两个,所以没法进行自动注入,所以报错。

怎么办?

要么给其中某个bean设置primary为true,表示找到多个时默认用这个。

或者给某个bean设置autowire-candidate为false,表示这个bean不作为自动注入的候选者。

还有一种就是@Qualifier, 首先,给两个bean分别定义一个qualifier:

    <bean id="user0" class="com.luban.entity.User" autowire-candidate="false"><property name="name" value="user0000"/><qualifier value="user00"/></bean><bean id="user1" class="com.luban.entity.User" ><property name="name" value="user1111"/><qualifier value="user11"/></bean>

同时在UserService中使用@Qualifier注解:

public UserService(@Qualifier("user00") User user11) {this.user = user11;}

 

还需要做一件事情,因为我们是使用的XML的方式使用Spring,所以还需要添加:

<context:annotation-config/>

这样@Qualifier注解才会生效,这样配置之后UserService中的user属性就会被赋值为@Qualifier("user00")所对应的user0这个bean。

@Qualifier注解是在使用端去指定想要使用的bean,而autowire-candidate和primary是在配置端。

@Qualifier的另外一种用法

定义一个:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {String value();
}

修改bean的定义

    <bean id="user0" class="com.luban.entity.User"><property name="name" value="user0000"/><qualifier type="com.luban.annotation.Genre" value="user00"/></bean><bean id="user1" class="com.luban.entity.User" ><property name="name" value="user1111"/><qualifier type="com.luban.annotation.Genre" value="user11"/></bean>

 

UserService中使用Genre注解:

public class UserService {private User user;public UserService(@Genre("user00") User user11) {this.user = user11;}public void test() {System.out.println(user.getName());}
}

这种用法相当于自定义@Qualifier注解,使得可以处理更多的情况。

同样,还可以这么做,定义两个注解:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier("random")
public @interface Random {}
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier("roundRobin")
public @interface RoundRobin {}

注意,是在自定义的Qualifier注解上指定了名字,这样就是可以直接使用自定义注解,而不用指定名字了。比如先修改bean的定义:

    <bean id="user0" class="com.luban.entity.User"><property name="name" value="user0000"/><qualifier type="com.luban.annotation.Random"/></bean><bean id="user1" class="com.luban.entity.User" ><property name="name" value="user1111"/><qualifier type="com.luban.annotation.RoundRobin"/></bean>

 

UserService中就可以这么用:

    public UserService(@RoundRobin User user11) {this.user = user11;}

 

  相关解决方案