导航目录

  • @Resources
    • Match by Name
    • Match by Type
    • Match by Qualifier
  • @Inject
    • Match by Type
    • Match by Qualifier
    • Match by Name
  • @Autowired

本文简述这三个Spring应用里常用的注解区别。

@Resources

官方文档里对@Resources的说明:

The @Resource annotation is part of the JSR-250 annotation collection and is packaged with Jakarta EE.

什么是JSR-250呢?访问这个链接:https://jcp.org/en/jsr/detail?id=250

里面有很多PDF可以下载:

打开一看,其实就是Java支持的注解的文档。这些文档是最权威的:

文档里介绍,@Resources对Bean的注入按照如下的优先级进行:

  1. Match by Name
  2. Match by Type
  3. Match by Qualifier

Match by Name

我们来看看Match by name的例子。下面的代码试图通过Match by Name注入一个名称为namedFile的Bean:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=AnnotationConfigContextLoader.class,classes=ApplicationContextTestResourceNameType.class)
public class FieldResourceInjectionIntegrationTest {@Resource(name="namedFile")private File defaultFile;@Testpublic void givenResourceAnnotation_WhenOnField_ThenDependencyValid(){assertNotNull(defaultFile);assertEquals("namedFile.txt", defaultFile.getName());}
}

Bean的定义在如下代码里:

@Configuration
public class ApplicationContextTestResourceNameType {@Bean(name="namedFile")public File namedFile() {File namedFile = new File("namedFile.txt");return namedFile;}
}

运行时,申明Bean依赖处的@Resource的Name属性和Bean定义处@Bean的Name属性值一致,Match by Name测试通过。

Match by Type

将使用bean的消费者代码里@Resource注解的name属性去掉,使其变成下面这样:

@Resource
private File defaultFile;

测试仍然通过,是因为Match by Name的探测机制执行失败后,进行下一轮Match by Type的探测,这一轮成功了。

Match by Qualifier

定义两个Bean:

@Configuration
public class ApplicationContextTestResourceQualifier {@Bean(name="defaultFile")public File defaultFile() {File defaultFile = new File("defaultFile.txt");return defaultFile;}@Bean(name="namedFile")public File namedFile() {File namedFile = new File("namedFile.txt");return namedFile;}
}

测试代码:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=AnnotationConfigContextLoader.class,classes=ApplicationContextTestResourceQualifier.class)
public class QualifierResourceInjectionIntegrationTest {@Resourceprivate File dependency1;@Resourceprivate File dependency2;@Testpublic void givenResourceAnnotation_WhenField_ThenDependency1Valid(){assertNotNull(dependency1);assertEquals("defaultFile.txt", dependency1.getName());}@Testpublic void givenResourceQualifier_WhenField_ThenDependency2Valid(){assertNotNull(dependency2);assertEquals("namedFile.txt", dependency2.getName());}
}

这一次执行失败,遇到异常org.springframework.beans.factory.NoUniqueBeanDefinitionException.

原因是因为我们的测试代码里,没有指定注入Bean的名称,因此Spring的Match by Name探测失败,进行Match by Type时,探测到两个类型一样的Bean,Spring框架不知道注入哪一个,所以就报异常了。

避免这个异常也很容易,使用@Qualifier.代码如下:


@Resource
@Qualifier("defaultFile")
private File dependency1;@Resource
@Qualifier("namedFile")
private File dependency2;

@Inject

这个注解定义在JSR-330里,文档链接:

https://jcp.org/en/jsr/detail?id=330

注入的优先级:

  1. Match by Type
  2. Match by Qualifier
  3. Match by Name

Match by Type

注意@Inject注入的最高优先级方式为Match by Type,而非@Resource的Match by Name.

任意定义一个待注入的Component:

@Component
public class ArbitraryDependency {private final String label = "Arbitrary Dependency";public String toString() {return label;}
}

使用@Inject注入:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=AnnotationConfigContextLoader.class,classes=ApplicationContextTestInjectType.class)
public class FieldInjectIntegrationTest {@Injectprivate ArbitraryDependency fieldInjectDependency;@Testpublic void givenInjectAnnotation_WhenOnField_ThenValidDependency(){assertNotNull(fieldInjectDependency);assertEquals("Arbitrary Dependency",fieldInjectDependency.toString());}
}

Match by Qualifier

定义一个新的待注入组件:

public class AnotherArbitraryDependency extends ArbitraryDependency {private final String label = "Another Arbitrary Dependency";public String toString() {return label;}
}

测试代码:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=AnnotationConfigContextLoader.class,classes=ApplicationContextTestInjectQualifier.class)
public class FieldQualifierInjectIntegrationTest {@Injectprivate ArbitraryDependency defaultDependency;@Injectprivate ArbitraryDependency namedDependency;@Testpublic void givenInjectQualifier_WhenOnField_ThenDefaultFileValid(){assertNotNull(defaultDependency);assertEquals("Arbitrary Dependency",defaultDependency.toString());}@Testpublic void givenInjectQualifier_WhenOnField_ThenNamedFileValid(){assertNotNull(defaultDependency);assertEquals("Another Arbitrary Dependency",namedDependency.toString());}
}

和之前@Resource的第一次试图通过Match by Type注入一样失败,遇到异常:NoUniqueBeanDefinitionException

利用@Qualifier避免这个异常:

@Inject
@Qualifier("defaultFile")
private ArbitraryDependency defaultDependency;@Inject
@Qualifier("namedFile")
private ArbitraryDependency namedDependency;

Match by Name

public class YetAnotherArbitraryDependency extends ArbitraryDependency {private final String label = "Yet Another Arbitrary Dependency";public String toString() {return label;}
}

消费者代码:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=AnnotationConfigContextLoader.class,classes=ApplicationContextTestInjectName.class)
public class FieldByNameInjectIntegrationTest {@Inject@Named("yetAnotherFieldInjectDependency")private ArbitraryDependency yetAnotherFieldInjectDependency;@Testpublic void givenInjectQualifier_WhenSetOnField_ThenDependencyValid(){assertNotNull(yetAnotherFieldInjectDependency);assertEquals("Yet Another Arbitrary Dependency",yetAnotherFieldInjectDependency.toString());}
}

application context代码:

@Configuration
public class ApplicationContextTestInjectName {@Beanpublic ArbitraryDependency yetAnotherFieldInjectDependency() {ArbitraryDependency yetAnotherFieldInjectDependency =new YetAnotherArbitraryDependency();return yetAnotherFieldInjectDependency;}
}

测试通过

@Autowired

这个注解和@Inject的用法一致,唯一区别就是@Autowired 属于Spring框架提供的注解。例子略。

要获取更多Jerry的原创文章,请关注公众号"汪子熙":

一文让您搞清楚@Resources, @Inject和@Autowired的区别相关推荐

  1. spring中@Inject和@Autowired的区别?分别在什么条件下使用呢?

    问题:spring中@Inject和@Autowired的区别?分别在什么条件下使用呢? 我在浏览SpringSource上的一些博客,在其他一个博客中,那个作者用了@Inject,但是我觉得他用@A ...

  2. @Inject.@Resource.@Autowired 的区别

    @Inject:Struts2的注解, @Resource : J2EE提供,用于注入,( j2ee提供的 ) 默认按名称装配,@Resource(name="beanName") ...

  3. 一文带你搞懂从动态代理实现到Spring AOP

    摘要:本文主要讲了Spring Aop动态代理实现的两种方式. 1. Spring AOP Spring是一个轻型容器,Spring整个系列的最最核心的概念当属IoC.AOP.可见AOP是Spring ...

  4. 一文带你搞懂C#多线程的5种写法

    一文带你搞懂C#多线程的5种写法 1.简介 超长警告! 在学习本篇文章前你需要学习的相关知识: 线程基本知识 此篇文章简单总结了C#中主要的多线程实现方法,包括: Thread 线程 ThreadPo ...

  5. 一文多图搞定制作自己的VOC数据集+使用yolov4训练自己的数据集+封装video测试脚本(基于ubuntu)

    一文多图搞定制作自己的VOC数据集+使用yolov4训练自己的数据集+封装video测试脚本(基于ubuntu) 制作VOC数据集 标注自己的数据集 整理数据集路径格式 训练数据集 环境 在Linux ...

  6. RPC框架:一文带你搞懂RPC

    RPC是什么(GPT答) ChatGPT回答: RPC(Remote Procedure Call)是一种分布式应用程序的编程模型,允许程序在不同的计算机上运行.它以一种透明的方式,将一个程序的函数调 ...

  7. 一文多图搞懂KITTI数据集下载及解析

    转载自一文多图搞懂KITTI数据集下载及解析-阿里云开发者社区 KITTI Dataset 1.图片下载:点击下载:https://s3.eu-central-1.amazonaws.com/avg- ...

  8. 渲染预览PDF文档,轻松搞定,这方案真香!

    渲染预览PDF文档,轻松搞定,这方案真香! 1.前言 2.列举一些文档预览解决方案: 3.列举一些文档解析生成解决方案: 4.案列赏析 5.准备工作: 6.模板讲解: 7.代码实现: 8.效果图: 9 ...

  9. 【干货知识】Redis:从应用到底层,一文帮你搞定

    1.基本类型及底层实现 1.1.String 用途: 适用于简单key-value存储.setnx key value实现分布式锁.计数器(原子性).分布式全局唯一ID. 底层:C语言中String用 ...

最新文章

  1. socket可以写成单例嘛_精读《设计模式 - Singleton 单例模式》
  2. 蒙特卡罗方法验证凯利公式
  3. CodeForces 474.D Flowers
  4. 【Nginx-20180108】Nginx的搭建文件服务器问题一则
  5. 如何在Java中将InputStream读取/转换为String?
  6. hql连接查询及外置命名查询
  7. QT4.7.3在dm6446平台上的移植[转]--make[1]: *** [assistant_cs.qm] Error 2
  8. cookie java 写入_JAVA中如何读写COOKIE
  9. [Usaco2011][bzoj2442][洛谷2527]修剪草坪解题报告(dp,贪心,单调队列)
  10. MYSQL中ALTER命令
  11. 深度 ghost linux系统,用Ghost实现Linux系统的备份
  12. 无法更改硬件兼容性时解决“虚拟机使用的是此版本 VMware Workstation 不支持的硬件版本”的方法
  13. 《CSS权威指南》读书笔记4
  14. matlab中muw,matlab – 获取属于凸包的点
  15. C语言系列1——hello world
  16. thinkphp配置mysql集群_ThinkPHP教程_PHP框架之ThinkPHP(五)【连接数据库与主从数据库设置】...
  17. 5G混战:改变世界不需要论资排辈
  18. ubuntu设置时间为utc标准时间
  19. Python 第几周和星期几
  20. 安全加密 - HSM vs Trustzone vs SHE vs Evita ,

热门文章

  1. 给老师的建议?????
  2. Linux---Google Chrome的安装
  3. JQuery + jquery插件
  4. 在对的时间 遇见对的人 是一种幸福
  5. SQL2K数据库开发三十之存储过程操作删除存储过程
  6. 碰撞的小球 ccf (模拟)
  7. *args 和**kwargs 的理解以及 函数的参数的总结
  8. Day 06 元组,字典,集合
  9. kubernetes --- Glusterfs
  10. iOS组件化-带你一步步实现项目的组件化