首先了解一下他们的用法,他们的共同点都是当做bean对象注入的时候用的。
如果他们放在一个字段上的时候,他们的本质都是通过执行set方法进行注入的。那为什么现在使用Autowired的时候会被警告,而使用Resource注解不会呢?再了解一下他们的使用区别。
- Autowired默认是使用byType的依赖方式进行注入,可以使用Qualifire注解进行指定name;而Resource注解则是使用byName的方式进行注入,可以直接在注解后面添加名称使用,例如
@Resource("userService")
。 - Autowired注解可以对构造器、方法、参数、字段使用,但是Resource注解只能对方法、字段使用。
- Autowired是由Spring官方提供的,而Resource是由java提供的。
- 当一个类启动的时候,它的初始化流程是静态变量或静态语句块 –> 实例变量或初始化语句块 –> 构造方法 -> Autowired,所以当在一个类的构造方法中使用注入的对象的某一个方法的时候,就会报一个NullPointerException的错误。
现在说一下为什么?
- 使用Spring的时候都基本会知道一句话就是“高内聚,低耦合”,所以说就有了IOC的设计模式也就是Spring使用的依赖注入DI。当我们使用Autowired的时候,假如没有使用Qualifire注解,那么Spring容器就会寻找同类型的进行注入。当不能有效的指明依赖,相信很多人都遇见过一个bug,依赖注入的对象为null,在启动依赖容器时遇到这个问题都是配置的依赖注入少了一个注解什么的。这种方式就过于依赖注入容器了,产生了高度耦合。当没有启动整个依赖容器时,这个类就不能运转,在反射时无法提供这个类需要的依赖。
- 依赖注入的核心思想之一就是被容器管理的类不应该依赖被容器管理的依赖,换成白话来说就是如果这个类使用了依赖注入的类,那么这个类摆脱了这几个依赖必须也能正常运行。然而使用变量注入的方式是不能保证这点的。可以在Spring官方中找到一句话 Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies(强制依赖就用构造器方式可选、可变的依赖就用setter注入)。
Resource有2个属性name和type。在spring中name属性定义为bean的名字,type这是bean的类型。如果属性上加Resource注解那么他的注入流程是
如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
如果指定了name,则从上下文中查找名称匹配的bean进行装配,找不到则抛出异常。
如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
如果既没有指定name,又没有指定type,则默认按照byName方式进行装配;如果没有匹配,按照byType进行装配。
Autowired只根据type进行注入,不会去匹配name。如果涉及到type无法辨别注入对象时,那需要依赖Qualifier或Primary注解一起来修饰。
个人认为,就像前面提到过的:Autowired是Spring提供的,它是特定IoC提供的特定注解,这就导致了应用与框架的强绑定,一旦换用了其他的IoC框架,是不能够支持注入的。而Resource是java提供的,它是Java标准,平常使用的IoC容器应当去兼容它,这样即使更换容器,也可以正常工作。