深度剖析 java中 @Autowired注解与@Resource注解的区别

相同点:

    (1) 表现的作用是一样的,都是用于属性注入

  (2) 均可标注在字段或属性的setter方法上。

    (3) 都可根据名称与类型进行查找对象

不同点:

(1)提供方不同:

        @Autowired是由org.springframework.beans.factory.annotation.Autowired提供,换句话说就是由Spring提供;

        @Resource是由javax.annotation.Resource提供,即JRE提供;

(2)处理器不同

      @Resource 是由 CommonAnnotationBeanPostProcessor 处理

       @Autowired 是由AutowiredAnnotationBeanPostProcessor 处理

      CommonAnnotationBeanPostProcessor 先于AutowiredAnnotationBeanPostProcessor 执行

(3)注入方式不同:

      @Autowired (默认情况) 

         1.通过@Qualifier指定名称,先按类型查找,再按指定名称查找,查到返回,查不到,抛出异常(NoSuchBeanDefinitionException:No qualifying bean of type available)

         2. 未指定名称,先按类型查找,发现多个,再按属性名称查找,查到返回,查不到异常(NoUniqueBeanDefinitionException:No qualifying bean of type available)

    @Resource (默认情况) 

          1. 注解有指定name属性, 则按照指定名称及类型查询,查到返回,查不到抛出异常(NoSuchBeanDefinitionException:No bean named  available)

          2.未指定名称,先按属性名称及类型查找,未发现,再按类型查询,发现多个,抛出异常(NoUniqueBeanDefinitionException:No qualifying bean of type  available);

(4)注解属性不同:

 @Autowired有一个属性required,默认为true

     required=true,则它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。

 @Resource有两个中重要的属性:name和type。

name属性指定查询的name,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象(从beanFactory中查找),当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象(从beanFactory中查找)。需要注意的是,@Resource如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时(从beanFactory中查找), @Resource注解会按类型装配。但一旦指定了name属性(isDefaultName=false),就直接按名称及类型装配了,如果按名称与类型查找不到就异常(NoSuchBeanDefinitionException:No qualifying bean of type available)。

type属性指定type, 如果设置了type属性,

      有指定name则取指定name(isDefaultName=false),然后直接按指定name及指定type查询,未找到抛出异常

      未指定name ,会从beanFactory中查询name(取属性名称)是否存在(!factory.containsBean(name)),如果存在,则按名称及type查询;如果不存在,则按指定type查找, 未找到或找到多个抛出异常

(5)通过setter方法注入处理不同
        @Resource  :有指定属性name, 则取name,无则取setter方法名中的名称(忽略set,不一定要set开头的方法名), 查找方式同作用在属性上。

        @Autowired :若过@Qualifier指定名称,则先按类型查找,再按指定名称查找。若未指定名称,则按类型查找,未找到或找到多个抛出异常

   另需要注意:spring装载过程为先装载@Resource ,后装载 @Autowired,若同时注解,如下:

@Resource  
@Autowired @Qualifier("i1")
private I i;

I为接口,有两个实现:I1,I2

会产生什么情况,是@Resource起作用?还是@Autowired起作用? 会不会报错?

答:不报错,是@Resource起作用,因为是通过CommonAnnotationBeanPostProcessor来处理,但为什么不报错,原因在于加了@Qualifier("i1"),其实@Qualifier也可以@Resource配合使用。

那又有产生个新疑问:@Qualifier与@Resource自身属性name有什么区别?

区别在于查找时机不同,@Resource的name是在处理器开始时就会根据name查找,有name就不会再根据type单独去查找。而@Qualifier是在根据type查找 之后,有结果时,再在结果集中根据bean名称筛选

你可能感兴趣的:(Java技术,java)