Spring-注解@Autowired、@Resource和@Qualifier

@Autowired和@Resource区别

在项目开发中,@Autowired@Resource这两个注解都可以用来给一个实例注入Bean,都可以写在字段上,或写在setter方法上,但他们之间是有区别的。

@Autowired

@Autowired是Spring框架中的注解,默认按类型注入,并且默认必须要求依赖对象必须存在(不存在会报错),可以通过required=false属性设置为非必须。

@Qualifier

因为@Autowired是按类型注入,如果容器中存在多个相同类型的Bean,那么这时候使用@Autowired注入就会报错,因为他不知道到底要注入哪一个。解决办法是使用@Qualifier注解,指定Bean的名称。比如如下的示例中有两个UserBean对象,使用@Autowired注解时,同时使用@Qualifier注解指定注入的名称为 user1 的Bean。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Configuration
public class UserBeanConfig {


@Bean
public UserBean user1() {
UserBean userBean = new UserBean();
userBean.setId(1L);
userBean.setName("张三");
return userBean;
}



@Bean
public UserBean user2() {
UserBean userBean = new UserBean();
userBean.setId(2L);
userBean.setName("李四");
return userBean;
}


}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

@RunWith(SpringRunner.class)
@SpringBootTest(classes = AnnotationBootstrap.class)
@Slf4j
public class IocBeanTest {

@Autowired
@Qualifier("user1")
private UserBean userBean;

@Autowired
protected ObjectMapper objectMapper;


@Test
public void userBeanGetTest() throws JsonProcessingException {
log.info(objectMapper.writeValueAsString(userBean));
}


}

输出:

1
INFO 8556 --- [ main] c.l.s.annotation.test.IocBeanTest : {"id":1,"name":"张三"}

@Resource

@Resource注解由J2EE提供的注解,默认按照名称进行装配,可以通过name属性指定名称,如果没有指定name属性,当注解写在字段上时,默认取字段名进行查找注入,如果写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

@Resource装配顺序总结:

  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配

所以上面@Autowired的例子,如果用@Resource来替换,则可以写成如下方式。
方式1:

1
2
3

@Resource
private UserBean user1;

方式2:

1
2
3

@Resource(name = "user1")
private UserBean userBean;

------ 本文完 ------