@Resource和@Autowired这两个注解都提供了将依赖对象注入到当前对象的功能,但二者却有众多区别,并且它们是常见的面试题之一,所以楼兰胡杨今天就来梳理它,希望对各位有所帮助。首先,梳理Spring中的byName与byType的基本概念;然后,介绍@Resource和@Autowired的使用方法,同时介绍了@Primary注解;最后,介绍二者的相同点和区别。

byName与byType的概念

  依赖注入是通过先在 Spring IoC 容器中查找对象,再将对象作为属性注入到当前类中。而查找的方式有两种:按名称(byName)查找或按类型(byType)查找,其中 @Autowired 和 @Resource 都是既使用了名称查找又使用了类型查找,但二者进行查找的顺序却截然相反。

  首先,梳理一下基本概念,初步了解什么是byType,什么是byName。

<bean id="userServiceImpl" class="cn.com.service.impl.UserServiceImpl" Autowire="byName">
</bean>
<bean id="userDao" class="cn.com.dao.impl.UserDaoImpl">
</bean>

  比如说上面这段XML代码,autowire="byType"的意思是通过class="cn.com.dao.impl.UserDaoImpl"来查找UserDaoImpl下所有的对象,代码autowire="byName"意思是通过id="userDao"来查找Bean中的userDao对象。

  byName就是通过Bean的id或者name去自动装配,如果一个bean的name 和另外一个bean的 property 相同,就自动装配。byType就是按Bean的Class的类型去自动装配,如果一个bean的数据类型和另外一个bean的property属性的数据类型兼容,就自动装配。

使用方法

   @Resource:先按照名称进行注入,如果按照名称查找不到,再根据类型进行查找。该注解属于JDK中的注解,它在项目中使用频率比较高。

  @Autowired:先按照类型(byType)自动装配,如果存在多个相同类型的 Bean 再按照名称(byName)自动装配。默认情况下要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,required属性的默认值为true。例如:

@Autowired(required=false)
@Qualifier("userService")
private UserService userService;

   如果当Spring上下文中存在不止一个UserDao类型的组件时,就会抛出BeanCreationException异常,为了解决这个问题,@Autowired注解可以借助

@Qualifier("组件名")注解来指明使用哪一个组件(实现类),实际上这是通过byName的方式实现。@Qualifier注解是java的规范,JRE标准

  @Primary:和@Qualifier 一样,可以使用@Primary注解让Spring进行自动装配的时候,默认使用哪个组件。使用场景经常是:对同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种的情况下, @Primary 就会大显身手。

  例如,UserService有两个实现类UserServiceImpl和UserServiceImplDefault,而我们想默认使用后者,可以使用@Primary修饰UserServiceImplDefault类:


@Service
public class UserServiceImpl implements UserService {
private static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class); @Autowired
private UserDao userDao;
@Override
public User getUserById(Long userId) {
logger.info("--------*****-----------");
return userDao.getUserById(userId);
}
} // ----------------- 我是分割线 ----------------- @Primary
@Component("defaultUserBean")
public class UserServiceImplDefault implements UserService {
private static Logger logger = LoggerFactory.getLogger(UserServiceImplDefault.class); @Autowired
private UserDao userDao;
@Override
public User getUserById(Long userId) {
logger.info("--------优先加载的组件-----------");
return userDao.getUserById(userId);
}
}

   @Resource,默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上时,默认取属性名作为bean名称寻找依赖对象。需要注意的是,@Resource如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时, 它会回退到按类型装配。但是需要格外注意的是,一旦用name指定加载的组件名称,就只能按名称自动装配。

@Resource (name= "userService" )
private UserService userService;

  @Inject:和@Autowired注解一样也是按类型注入bean,但是没有required属性。使用此注解时需要导入javax.inject包。

  以上三个注解主要用于为类中属性自动注入bean,它们可以将(Spring IOC容器中的对象)装配到某些类的属性中。

Spring注解实战

  例如,使用@Repository注册UserDao的组件到Spring容器:

@Repository
public interface UserDao {
User getUserById(Long userId);
}

  使用@Autowired把组件UserDao装配到UserServiceImpl实现类中:

@Service
public class UserServiceImpl implements UserService {
private static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class); @Autowired
private UserDao userDao;
@Override
public User getUserById(Long userId) {
logger.info("--------*****-----------");
return userDao.getUserById(userId);
}
}

  这里,@Service将UserServiceImpl注册成组件托管给Spring容器。

相同点与区别

  相同点:@Resource的作用相当于@Autowired,均可标注在字段或属性的setter方法上。

  不同点

  (1)提供方:@Autowired是由Spring提供,即由org.springframework.beans.factory.annotation.Autowired提供;@Resource是由JDK提供,即由javax.annotation.Resource提供,来自于 JSR-250,需要JDK 6及以上版本。

  (2)注入方式:@Autowired只按照byType 注入;可以借助@Qualifier注解来指明使用哪一个实现类,@Resource默认按byName自动注入,也提供按照byType 注入。

  (3)注解属性:@Autowired 注解只支持设置一个 required 属性,而 @Resource 注解支持七种属性。@Autowired 按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。

  (4)依赖注入的支持不同:@Autowired 可以写在构造器上,用于注入bean,@Resource不可以。@Autowired 支持三种常见依赖注入方式——属性注入、构造方法注入和 Setter 注入,而 @Resource 只支持属性注入和 Setter 注入。

  (5)@Resource注解不支持spring的@Primary注解优先注入,但是@Autowired支持。

结束语

  @Autowied、@Resource或@Inject什么时候实现自动装配?启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器自动查找需要的组件,并装配给该对象的属性。

  推荐使用@Resource注解,使代码更加优雅,用它修饰字段后,就不用写setter方法了,并且这个注解是属于J2EE的,减少了与Spring的耦合。

  作为程序员,要有“刨根问底”的精神。知其然,更要知其所以然。这篇文章希望能抽丝剥茧,还原背后的原理。

自动装配组件@Resource和@Autowired的区别的更多相关文章

  1. 【Spring注解驱动开发】使用@Autowired@Qualifier@Primary三大注解自动装配组件,你会了吗?

    写在前面 [Spring专题]停更一个多月,期间在更新其他专题的内容,不少小伙伴纷纷留言说:冰河,你[Spring专题]是不是停更了啊!其实并没有停更,只是中途有很多小伙伴留言说急需学习一些知识技能, ...

  2. 【Java面试】@Resource 和 @Autowired 的区别

    Hi,大家好,我是Mic. 一个工作2年的粉丝,问我一个Spring里面的问题. 希望我能从不同的视角去分析,然后碾压面试官. 这个问题是: "@Resource和@Autowired&qu ...

  3. @Resource和@Autowired的区别

    @Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了.@Resource有两个属性是比较重要的,分 ...

  4. spring @Resource和@Autowired的区别

    @Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了.@Resource有两个属性是比较重要的,分 ...

  5. Spring注解@Resource和@Autowired的区别

    @Resource和@Autowired都是用来做bean的依赖注入的,两者都可以写在字段和setter方法上. java为我们提供了 javax.annotation.Resource这个注解. s ...

  6. spring的自动装配,骚话@Autowired的底层工作原理

    前言 开心一刻 十年前,我:我交女票了,比我大两岁.妈:不行!赶紧分! 八年前,我:我交女票了,比我小两岁,外地的.妈:你就不能让我省点心? 五年前,我:我交女票了,市长的女儿.妈:别人还能看上你?分 ...

  7. springboot自动装配(2)---实现一个自定义自动装配组件

    对于springboot个人认为它就是整合了各种组件,然后提供对应的自动装配和启动器(starter),基于这个流程去实现一个定义的装配组件 还是这张图 一.创建自己的自动配置工程, spring.f ...

  8. 详细解析@Resource和@Autowired的区别 , 以及@Qualifier的作用

    (41)  (0) 首先 . @Resource是javax.annotation 包中的注解类 , 是jdk中封装的 . @AutoWired是spring的中注解,依赖于spring上下文. 相同 ...

  9. 简析@Resource 和 @Autowired的区别

    @Autowird @Autowird 属于spring框架,默认使用类型(byType)进行注入,例如下面代码: @Autowired public IUserService userService ...

  10. @Resource与@Autowired注解的区别(转)

    Spring不但支持自己定义的@Autowired注解,还支持由JSR-250规范定义的几个注解.如:@Resource.@PostConstruct及@PreDestroy 1.@Autowired ...

随机推荐

  1. 寻找旋转排序数组中的最小值 II

    地址:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/ <?php /** 154. 寻找旋转排 ...

  2. 如何用Forest方便快捷地在SpringBoot项目中对接DeepSeek

    ​ 一. 环境要求 JDK 8 / 17 SpringBoot 2.x / 3.x Forest 1.6.4+ Fastjson2 依赖配置 除了 SpringBoot 和 Lombok 等基础框架之 ...

  3. 震惊!AI 编程竟然让程序员 “失业” 了?真相让人意外

    在科技飞速发展的当下,AI 编程的异军突起无疑成为了整个编程领域乃至社会各界热议的焦点. 去年,全球首个AI程序员Devin横空出世,不仅能独立完成代码开发.修复Bug,甚至能通过阅读技术文档自主学习 ...

  4. LLM · RL | Plan4MC:使用有向无环图 high-level planning + 基于 RL 执行 low-level policy

    文章标题:Skill Reinforcement Learning and Planning for Open-World Minecraft Tasks 最初发表时间:2023.03 arxiv:h ...

  5. idea 登录提示Server's certificate is not trusted

    原因:你本地的idea证书不可以 解决方式1: 你去安装一个正版的: 解决方式2: 设置接受不受信任证书即可. AS:File - Settings - Tools - Server Certific ...

  6. go module基本使用

    前提 go版本为1.13及以上 官方文档 如果你想更深层次的了解GO MODULE的意义及开发者们的顾虑,可以直接访问官方文档(EN) https://github.com/golang/go/wik ...

  7. Flask快速入门3

    十一,Flask Cookies Cookie以文本文件的形式存储在客户端的计算机上.其目的是记住和跟踪与客户使用相关的数据,以获得更好的访问者体验和网站统计信息. Request对象包含Cookie ...

  8. MFC中AfxBeginThread、AfxEndThread、GetExitCodeThread的配合使用(工作者线程)

    //线程入口函数(全局) UINT MyThreadProc(LPVOID pParam) { //在需要添加返回值的地方 if (...) { AfxEndThread(0); return 0; ...

  9. 如何打造你自己的 AI 软件工程师(像 Devin 那样)

    扩展 DeepSeek 的强化学习蓝图路线到AI的其他方面 Nikhil Anand 图片由GPT-4o生成 "AI 软件工程师"这个概念,其实已经不再遥远了.已经有一些技术在逐步 ...

  10. Vim 操作-替换

    Vim 操作-替换 substitute :[range]s[ubstitute]/{pattern}/{string}/{flag} 替换的操作范围以行为基础: %-全局范围,m,n-使用逗号隔开的 ...