Spring/Spring-Boot 学习 @Autowired 与 @Resource

@Autowired 和 @Resource的区别

如果在网上搜一下@Autowired 和 @Resource 的区别, 大多数的答案都是说 @Autowired 默认按byType注入, @Resource 默认按byName注入。
首先需要理解什么叫byName, 什么叫byType。顾名思义, byName是按照名称注入,这个名称指的是什么呢?

Spring容器生成bean的时候bean的名称,如果通过xml文件注入,bean的名称由 id属性确定;如果使用 配置类+注解的方式注入(@Configuration+@Bean), 则由@Bean注解标注的方法的名称确定。

byType的方式则是按照类型的方式注入,类型指的就是bean的类型的名称。

Spring容器生成的bean是哪个类型的bean, 如果通过xml文件注入,bean的类型由class属性给出的全限定的类型确定;如果使用 配置类+注解的方式注入(@Configuration+@Bean), 则由@Bean注解标注的方法的返回值确定。

了解了什么是byName什么是byType, 回过头来再看网上说的这句话:
@Autowired 默认按byType注入, @Resource 默认按byName注入。
意思是说@Autowired在注入的时候,会去容器中找类型与声明的引用的类型一样的对象来注入;而@Resource方法,会去容器中找bean名称与声明的对象的名称一样的对象来注入。

@Resource

我们知道,其实一个类我们可以实例化多个对象,这些对象都是同一类型的。如果在容器中我们对一个类实例化了多个对象, 那么byType方法就不生效了,因为现在按照类型去容器中找对象,我们会找到多个beanspring不知到要用哪个bean。也就是说,这个时候@Autowired注解就不会生效。事实上是只要你用的spring版本高于3.x, @Autowired方法一样会生效。具体的原因是@Autowired会优先按byType注入,如果发现容器中有多个这个类型的实例,会再按bean的名称去匹配。具体的分析见 Spring/Spring学习 自动装配@Autowired 和 @Resource
总结一下就是:

  • spring 3.x以前的版本,@Autowired默认按byType注入,当容器中存在多个同一type的实例时,会报错;
  • @Resource默认按byName注入;
  • spring 3.x及以后的版本,·@Autowired默认按byName注入,当容器中存在多个同一type的是实例时,会在这些实例中按byName`挑选匹配的实例。
  • @Qualifier注解可以指定@Autowired注解按@Qualifier中指定的bean名称注入。
    @Autowired
    @Qualifier("student01")
    Student student;

下面内容转自 Autowired与@Resource的用法和区别

@Resource

@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

@Resource装配顺序

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

@Autowired与@Resource的区别

  1. @Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上。
  2. @Autowired默认按类型装配(这个注解是属于spring的),默认情况下必须要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false。
  3. @Resource(这个注解属于J2EE的),默认按照名称进行装配,名称可以通过name属性进行指定, 
    如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。 当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
    ps: @Resource注解在字段上,这样就不用写setter方法了,并且这个注解是属于J2EE的,减少了与spring的耦合。

@Bean 注入和 @Value注入的先后问题

使用注解注入List对象的两种方法

posted @ 2019-11-21 11:47  lllunaticer  阅读(585)  评论(0编辑  收藏  举报