相同点:
(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名称筛选