@Resource和@Autowired的不同之处
1.相同点
@Resource和@Autowired这两个注解的作用都是在Spring生态里面去实现Bean的依赖注入
2.不同点
2.1 @Autowired
首先,@Autowired是Spring里面提供的一个注解,默认是根据类型来实现Bean的依赖注入。
@Autowired注解里面有一个required属性默认值是true,表示强制要求bean实例的注入,在应用启动的时候,如果IOC容器里面不存在对应类型的Bean,就会报错。当然,如果不希望自动注入,可以把这个属性设置成false。
@Controller
public class HelloController {
@Autowired(required = true)
private HelloService helloService;
@ResponseBody
@RequestMapping("/hello")
public String hello() {
return helloService.hello();
}
}
但是当项目有多个相同类型的Bean被定义时,使用@Autowired会报错
@org.springframework.context.annotation.Configuration
public class Configuration {
@Bean("hello1")
public HelloService hello1() {
return new HelloServiceImpl();
}
@Bean("hello2")
public HelloService hello2() {
return new HelloServiceImpl();
}
}
所以Spring启动的时候,会提示一个错误,大概意思原本只能注入一个单实例Bean,但是在IOC容器里面却发现有多个,导致注入失败。
Field helloService in com.zte.helloworld.contorller.HelloController required a single bean, but 3 were found:
- helloServiceImpl: defined in file [D:\JavaWorkSpace\code\helloworld\target\classes\com\zte\helloworld\service\impl\HelloServiceImpl.class]
- hello1: defined by method 'hello1' in class path resource [com/zte/helloworld/config/Configuration.class]
- hello2: defined by method 'hello2' in class path resource [com/zte/helloworld/config/Configuration.class]
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
针对这个问题,我们可以使用 @Primary或者@Qualifier这两个注解来解决。
@Primary表示主要的bean,当存在多个相同类型的Bean的时候,优先使用声明了@Primary的Bean。
@Qualifier的作用类似于条件筛选,它可以根据Bean的名字找到需要装配的目标Bean。
@Controller
public class HelloController {
@Autowired(required = true)
@Qualifier("hello1")
private HelloService helloService;
@ResponseBody
@RequestMapping("/hello")
public String hello() {
return helloService.hello();
}
}
2.2 @Resource
@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持。
它的使用方式和@Autowired完全相同,最大的差异于@Resource可以支持ByName和ByType两种注入方式。
如果使用name,Spring就根据bean的名字进行依赖注入,如果使用type,Spring就根据类型实现依赖注入。
如果两个属性都没配置,就先根据定义的属性名字去匹配,如果没匹配成功,再根据类型匹配。两个都没匹配到,就报错。
@Controller
public class HelloController {
// @Autowired(required = true)
// @Qualifier("hello1")
// private HelloService helloService;
@Resource(name = "helloService01")
private HelloService01 helloService01;
@Resource(type = HelloService02.class)
private HelloService02 helloService02;
@ResponseBody
@RequestMapping("/hello")
public String hello() {
return helloService02.hello();
}
}