【Java 面试篇】@Autowire和@Resource的区别
面试系列测试代码请参考:博主的Gitee仓库
-
说说@Autowired和@Resource的区别
在Spring中,@Autowired和@Resource都是用于注入Bean的注解。它们的作用相似,但是它们的注入方式和使用场景略有不同。
-
@Autowired
@Autowired注解是Spring提供的一种自动装配的方式,它可以自动将匹配类型的Bean注入到目标Bean中。当一个Bean中有多个与要注入的类型相匹配的Bean时,@Autowired可以通过@Qualifier注解指定要注入的Bean的名称。
@Autowired注解默认按照类型匹配Bean,如果一个Bean没有匹配类型的Bean,则会抛出NoSuchBeanDefinitionException异常。但是,可以使用@Autowired(required = false)来避免这种异常的抛出,这样如果没有匹配的Bean,则会将该属性设置为null。
-
@Resource
@Resource注解也是Spring提供的一种自动装配的方式,它可以根据Bean的名称或类型自动注入Bean。@Resource注解有两个重要的属性:name和type。name属性指定要注入的Bean的名称,type属性指定要注入的Bean的类型。
@Resource注解按照名称和类型进行匹配,如果指定了name属性,则会按照名称进行匹配;如果没有指定name属性,则会按照类型进行匹配。如果没有找到匹配的Bean,则会抛出NoSuchBeanDefinitionException异常。
需要注意的是,@Resource注解是J2EE提供的,而@Autowired注解是Spring提供的。因此,如果在非Spring环境下使用@Resource注解,可能会导致兼容性问题。
总结:在Spring中,@Autowired注解按照类型进行匹配,@Resource注解按照名称和类型进行匹配。@Autowired注解是Spring提供的,而@Resource注解是J2EE提供的。
-
-
自动装配的匹配策略有:
default
:默认匹配策略byType
:按照类型匹配byName
:按照名称匹配
-
@Autowired使用注意事项:
-
自动装配的Bean必须要被Spring管理,即:自动装配的Bean必须注入IoC容器,交给IoC容器管理。如果一个Bean没有匹配类型的Bean,则会抛出NoSuchBeanDefinitionException异常。但是,可以使用@Autowired(required = false)来避免这种异常的抛出,这样如果没有匹配的Bean,则会将该属性设置为null。
交给Spring管理的方式有:注解配置,XML配置
-
自动装配的Bean必须提供构造方法,默认是寻找无参构造方法,无参未找到就会找有参,如果没有找到任何一个带有参数的构造函数,则会抛出 NoSuchMethodException 异常。但是如果使用了其他的注解来声明Bean,比如使用@Component或@Service注解,这些注解中会存在默认的无参构造方法的要求。因此,在这种情况下,需要确保Bean拥有无参构造方法,否则无法正常实例化。
-
默认采用byType策略进行匹配,当匹配到多个同类型的Bean时,编译阶段就会报错,此时需要使用
@Qualifier
注解指定Bean的名称(也就是改用 byName 匹配策略),Bean默认的name是类名首字母小写(可通过Component的value属性重新指定Bean的 name) -
为什么Spring官方不推荐在成员变量上使用@Autowired?
-
成员变量的注入时机不确定
将@Autowired注解标注在成员变量上时,Spring框架会在创建Bean的时候自动注入成员变量。但是,在注入成员变量之前,Spring框架还没有对该Bean进行初始化,因此,成员变量的值可能会为null,这会导致空指针异常。
-
无法进行final修饰的成员变量注入
由于@Autowired注解是在运行时注入Bean的,因此它不能注入final修饰的成员变量。
-
不利于单元测试
在进行单元测试时,可能需要模拟Bean的行为,此时如果将@Autowired注解标注在成员变量上,则无法通过setter方法进行Bean的mock操作,从而影响了单元测试的进行。
因此,推荐将@Autowired注解标注在类的构造函数、setter方法或方法参数上,这样可以明确注入的时机,并且可以避免成员变量的空指针异常。同时,这种做法也更利于单元测试。
-
-
-
@Autowired和@Resource的比较
-
功能相同。@Autowired和@Resource注解都是作为Bean对象注入的时候使用的
-
默认匹配策略不同。@Autowird注解默认通过 byType 方式注入,而@Resource注解默认通过 byName 方式注入
-
Autowired优点:
- 注入方式更灵活,可以通过构造函数、setter方法或者方法参数进行注入。
- 支持按照类型、名称或者属性名称进行注入,具有更多的匹配策略。
- 可以支持基于Java编程的配置,不需要依赖于注解。
@Resource优点:
- 可以指定Bean的名称,从而避免了按照类型进行注入时可能存在的多个相同类型的Bean。
- 可以进行细粒度的控制,比如可以指定要注入的Bean的属性名,以及是否允许为null。
- 支持基于XML配置的方式,可以更方便地管理Bean。
因此,如果需要灵活的注入方式,以及更多的匹配策略,建议使用@Autowired注解;如果需要更细粒度的控制,以及XML配置的支持,建议使用@Resource注解。当然,在实际开发中,两个注解也可以混合使用。
-
J2EE:Java企业级应用程序开发规范,类似于JDBC,是一套标准,现在已经更名为JavaEE了 ↩︎