@Resource与@Autowired用法区别

青旅半醒 2022-05-13 04:20 259阅读 0赞
  1. spring中,@Resource@Autowired都是做bean的注入时使用。使用过程中,有时候@Resource @Autowired可以替换使用;有时,则不可以。
  2. 下面,根据自己的学习,整理下这两个注解使用中的共同点和不同点,及用法上的不同。
  3. 共同点
  4. @Resource@Autowired都可以作为注入属性的修饰,在接口仅有单一实现类时,两个注解的修饰效果相同,可以互相替换,不影响使用。
  5. 不同点
  • @Resource是Java自己的注解,@Resource有两个属性是比较重要的,分是name和type;Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
  • @Autowired是spring的注解,是spring2.5版本引入的,Autowired只根据type进行注入,不会去匹配name。如果涉及到type无法辨别注入对象时,那需要依赖@Qualifier或@Primary注解一起来修饰。
  1. 我们创建一个简单的springboot项目demo
  2. 定义一个接口Human.java,里面一个方法 runMarathon
  3. 一个实现类Man.java
  4. 一个ControllerHumanController.java,里面注入Human接口的实现
  5. ![70][]
  6. 附各Java类源码
  7. package com.example.annotation.service;
  8. /**
  9. * service接口定义
  10. * @author Administrator
  11. */
  12. public interface Human {
  13. /**
  14. * 跑马拉松
  15. * @return
  16. */
  17. String runMarathon();
  18. }
  19. package com.example.annotation.service.impl;
  20. import com.example.annotation.service.Human;
  21. import org.springframework.stereotype.Service;
  22. /**
  23. * service接口第一实现类
  24. * @author Administrator
  25. */
  26. @Service
  27. public class Man implements Human {
  28. public String runMarathon() {
  29. return "A man run marathon";
  30. }
  31. }
  32. package com.example.annotation.controller;
  33. import javax.annotation.Resource;
  34. import org.springframework.web.bind.annotation.RequestMapping;
  35. import org.springframework.web.bind.annotation.RestController;
  36. import com.example.annotation.service.Human;
  37. /**
  38. * controller层实现类
  39. * @author Administrator
  40. */
  41. @RestController
  42. @RequestMapping("/an")
  43. public class HumanController {
  44. @Resource
  45. private Human human;
  46. @RequestMapping("/run")
  47. public String runMarathon() {
  48. return human.runMarathon();
  49. }
  50. }
  51. 至此,代码整理完成,启动springboot,浏览器地址栏输入[http://localhost:8080/an/run][http_localhost_8080_an_run]

70 1

改动一:

将HumanController.java 类中的注解替换为@Autowired,再次启动,可以正常访问,与上图相同,这里不再贴访问结果图。

改动二:

再增加一个实现类Woman.java

  1. package com.example.annotation.service.impl;
  2. import com.example.annotation.service.Human;
  3. import org.springframework.stereotype.Service;
  4. /**
  5. * service接口第二实现类
  6. * @author Administrator
  7. */
  8. @Service
  9. public class Woman implements Human {
  10. public String runMarathon() {
  11. return "An woman run marathon";
  12. }
  13. }

HumanController.java 注解使用@Resource

  1. @Resource
  2. private Human human;

启动springboot,控制台会报错,报错信息太多,截取关键信息

  1. 2018-09-10 16:07:10.362 WARN 5592 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'humanController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.annotation.service.Human' available: expected single matching bean but found 2: man,woman

找关键信息 expected single matching bean but found 2: man,woman,被期望的单一结果被匹配到两个结果man和woman。

这里,我们需要借助@Resource注解的name属性或@Qualifier来确定一个合格的实现类

代码修改为

  1. @Resource(name="woman")
  2. private Human human;

  1. @Resource
  2. @Qualifier("woman")
  3. private Human human;

上面,我们指定了Human接口的实现类是Woman.java,启动springboot,访问 http://localhost:8080/an/run

70 2

改动三:

在改动二的基础上,将注解替换为@Autowired,启动报错

  1. Description:
  2. Field human in com.example.annotation.controller.HumanController required a single bean, but 2 were found:
  3. - man: defined in file [D:\DEV_ENV\springbootws\annotation\target\classes\com\example\annotation\service\impl\Man.class]
  4. - woman: defined in file [D:\DEV_ENV\springbootws\annotation\target\classes\com\example\annotation\service\impl\Woman.class]
  5. Action:
  6. 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

报错信息很明显,HumanController需要一个bean实现,但是找到了两个 man 和woman

解决方案:使用@Primary注解,在有多个实现bean时告诉spring首先@Primary修饰的那个;或者使用@Qualifier来标注需要注入的类。

@Qualifier修改方式与改动二的相同,依然是修改HumanController.java 中间注入的Human上面,这里不再复述

@Primary是修饰实现类的,告诉spring,如果有多个实现类时,优先注入被@Primary注解修饰的那个。这里,我们希望注入Man.java ,那么修改Man.java为

  1. package com.example.annotation.service.impl;
  2. import org.springframework.context.annotation.Primary;
  3. import org.springframework.stereotype.Service;
  4. import com.example.annotation.service.Human;
  5. /**
  6. * service接口第一实现类
  7. * @author Administrator
  8. */
  9. @Service
  10. @Primary
  11. public class Man implements Human {
  12. public String runMarathon() {
  13. return "A man run marathon";
  14. }
  15. }

启动springboot后,可以看到注入的已经是Man.java 了。

70 3

以上,个人学习总结,如有不当之处,欢迎留言批评斧正。谢谢

发表评论

表情:
评论列表 (有 0 条评论,259人围观)

还没有评论,来说两句吧...

相关阅读