@Autowired和@Resource的区别
@Resource
有两个常用属性name、type,所以分4种情况
- 指定name和type:通过name找到唯一的bean,找不到抛出异常;如果type和字段类型不一致,也会抛出异常
- 指定name:通过name找到唯一的bean,找不到抛出异常
- 指定type:通过tpye找到唯一的bean,如果不唯一,则抛出异常:NoUniqueBeanDefinitionException
- 都不指定:通过字段名作为key去查找,找到则赋值;找不到则再通过字段类型去查找,如果不唯一,则抛出异常:NoUniqueBeanDefinitionException
@Autowired
@Autowired由Spring提供,只按照byType注入
@Autowired只有一个属性required,默认值为true,为true时,找不到就抛异常,为false时,找不到就赋值为null
@Autowired按类型查找,如果该类型的bean不唯一,则抛出异常;可通过组合注解解决@Autowired()@Qualifier("baseDao")
相同点
- Spring都支持
- 都可以作用在字段和setter方法上
不同点
- Resource是JDK提供的,而Autowired是Spring提供的
- Resource不允许找不到bean的情况,而Autowired允许(
@Autowired(required = false)
) - 指定name的方式不一样,
@Resource(name = "baseDao")
,@Autowired()@Qualifier("baseDao")
- Resource默认通过name查找,而Autowired默认通过type查找
总结
@Autowired自动注解,一个类,俩个实现类,Autowired就不知道注入哪一个实现类,需要配合@Qualifier按照name注入,而Resource有name属性,可以区分。
举例说明
@Autowired
在service层,让StudentServiceImpl1,StudentServiceImpl2实现StudentService借口
在controller层,使用@Autowired注入则会抛出异常,idea直接提示使用@Qualifier进行区分,解决方案有四种:
1:@Autowired+@Qualifier("studentServiceImpl1")则可以进行区分
2:去掉一个StudentService的实现类,则可以直接按照类型进行装配
3:**@Autowired+@Primary****,自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常。(只对接口的多个实现生效)
4: @Resource(name = "studentServiceImpl1"),不指定name会抛出异常。如果只有StudentServiceImpl1,删掉StudentServiceImpl2,则可以直接使用@Resource,根据类型查找唯一值
@Service
public class StudentServiceImpl1 implements StudentService {
@Override
public void getStudentAge() {
System.out.println("查到学生的年龄");
}
}
@Service
public class StudentServiceImpl2 implements StudentService {
@Override
public void getStudentAge() {
System.out.println("查到学生的年龄");
}
}
错误写法:
@Slf4j
@RestController
public class StudentController {
@Autowired
@Qualifier("studentServiceImpl1")
StudentService studentService;
@RequestMapping("/student")
public String handle01(){
studentService.getStudentAge();
return "student";
}
}
正确的@Autowired+@Qualifier写法:
@Slf4j
@RestController
public class StudentController {
@Autowired
@Qualifier("studentServiceImpl1")
StudentService studentService;
@RequestMapping("/student")
public String handle01(){
studentService.getStudentAge();
return "student";
}
}
正确的@Autowired+@Primary写法:
@Service
@Primary
public class StudentServiceImpl1 implements StudentService {
@Override
public void getStudentAge() {
System.out.println("查到学生的年龄");
}
}
正确的@Resource写法:
@Slf4j
@RestController
public class StudentController {
@Resource(name = "studentServiceImpl1")
StudentService studentService;
@RequestMapping("/student")
public String handle01(){
studentService.getStudentAge();
return "student";
}
}