@Resource详解-代码示例
@Resource注解详解
- 属性介绍
- @Resource 的装配规则
- 灵魂总结
- 先来看下@Resource的应用场景
- 代码演示
- 默认情况
- 装配代码
- 运行测试
- 分析
- byName (name默认属性名)
- 装配代码
- 运行测试
- 分析
- byName (name显示指定)
- 装配代码
- 运行测试
- 分析
- byType 显示指定
- 装配代码
- 运行测试
- 分析
- finally
此注解来源于JSR规范(Java Specification Requests),其作用是找到依赖的组件注入到应用来,它利用了JNDI(Java Naming and Directory Interface Java命名目录接口 J2EE规范之一)技术查找所需的资源。
网上查了些资料看的有点晕晕, 这里用例子来说明 @Resource的用法 , 以及需要注意的问题
属性介绍
name:资源的JNDI名称。在spring的注入时,指定bean的唯一标识。
type:指定bean的类型。
lookup:引用指向的资源的名称。它可以使用全局JNDI名称链接到任何兼容的资源。
authenticationType:指定资源的身份验证类型。它只能为任何受支持类型的连接工厂的资源指定此选项,而不能为其他类型的资源指定此选项。
shareable:指定此资源是否可以在此组件和其他组件之间共享。
mappedName:指定资源的映射名称。
description:指定资源的描述。
@Resource 的装配规则
默认情况下,即所有属性都不指定,它默认按照byType的方式装配bean对象。
如果指定了name,没有指定type,则采用byName。
如果没有指定name,而是指定了type,则按照byType装配bean对象。
当byName和byType都指定了,两个都会校验,如果找不到,或者找到多个(比如byName的方式找到了BeanA, ByType的方式找到了BeanB ) 这种情况也是不会成功的.
上述略显官方的味道的解释,相信不少人也是晕晕的 , 也对这个"默认值" 情况解释的不到位 , 下面来个灵魂总结.
灵魂总结
注意: !!! type和name的根本逻辑就是 type是划定一个范围 , 然后name 在其中选择一个
举个栗子:
- 如果 type 只匹配了 一个 ( 1 ) , 那么成功装备结果 必然是 1 , 如果name只有找到了1 , 或者没有找到的情况下才会配置成功( 没有显示指定name值, 默认为变量名) , name如果在容器中找到了非1 的bean ,则会报类型错误.
- 如果type 匹配了 ( 1 , 2 , 3 ) 多个实例 , 那么name只有匹配到 其中一个,才会装配成功, 如果一个也匹配不到 , 则会报错 ,因为spring不知道到底要装配哪个实例.
- 如果type一个都没有匹配到,那就直接凉凉了 ,报错:No qualifying bean of type xxx 的错误, 即使name指定的值在容器中找到了符合条件的bean实例, 也会报 类型不符合的错误.
先来看下@Resource的应用场景
@Resource的应用场景一般都是在装配的时候出现了多个符合条件的bean , 这时候用@Autowired注解自动装配就会出现了问题 . 此时就可以用@Resource注解类解决问题 . (@Qualifier + @Autowired 也可以实现, 这里主要说下@Resource注解) , 通常就是解决多态的问题.
代码演示
这里示例将@Resource 放在了类的属性上
首先有个HelloService接口:
package com.resource.service;
public interface HelloService {void sayHello();
}
两个实现类 , HelloServiceImpl1 和 HelloServiceImpl2 , 实现的sayHello()方法,分别在控制台打印出 hello one! , hello two! 如下:
package com.resource.service.impl;
@Component
public class HelloServiceImpl1 implements HelloService {public void sayHello() {System.out.println("hello one!");}
}
package com.resource.service.impl;
@Component
public class HelloServiceImpl2 implements HelloService {public void sayHello() {System.out.println("hello two!");}
}
业务类UseService 实现属性装配
package com.resource;
@Component
public class UseService {//@Qualifier("helloServiceImpl1")//@Autowired//private HelloService helloService;@Resourceprivate HelloService helloServiceImpl;public void say(){helloServiceImpl.sayHello();}
}
测试类
public static void main(String[] args) {//1.创建容器AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext("com");//2.获取对象UseService useService = ac.getBean("useService", UseService.class);useService.say();}
默认情况
装配代码
其它代码不变
@Resourceprivate HelloService helloServiceImpl;public void say(){helloServiceImpl.sayHello();}
运行测试
这时候如果什么都不指定, 运行则会报错如下:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException
: No qualifying bean of type 'com.resource.service.HelloService' available
: expected single matching bean but found 2: helloServiceImpl1,helloServiceImpl2
分析
@Resource是用 ByType和ByName 来装配的, 如果没有显示的通过type属性和name属性指定 , “就会找其默认值”
在这个示例中type就是HelloService.class , 又因为其是接口, spring在容器中找到了其两个已经注入容器的实现类分别为 helloServiceImpl1 , helloServiceImpl2 这两个实例. (范围)
而name 也没有通过属性执行 , name默认值就是变量的名称 helloServiceImpl , 显然spring容器中是没有的. (后续会通过测试验证)
通过默认指定值得ByType和ByName 其结果就是得到了两个符合要求的实例 , 而name也没有完成在type后有多个实例的情况下 “选一个” . 所有会有上述的把报错信息.
byName (name默认属性名)
装配代码
其它代码不变
@Resourceprivate HelloService helloServiceImpl1;public void say(){helloServiceImpl1.sayHello();}
这个变化就是上个示例中将属性名从helloServiceImpl 改成了 helloServiceImpl1 .
运行测试
hello one!
Process finished with exit code 0
分析
这里同样byType后 有两个实例 helloServiceImpl1 , helloServiceImpl2 , 而name没有显示指定, 默认为变量名 helloServiceImpl1 , 也完成了选一个的任务, 进而装配成功!
byName (name显示指定)
装配代码
其它代码不变
@Resource(name="helloServiceImpl2")private HelloService helloServiceImpl1;public void say(){helloServiceImpl1.sayHello();}
这个变化就是上个示例中 指定了name属性的值
运行测试
hello two!
Process finished with exit code 0
分析
可以看到属性名为helloServiceImpl1 , 显示指定的是helloServiceImpl2 , 即如果显示指定name的值得话就取该值, 相当于是对默认的变量名覆盖了(可以这样理解). 就是有显示指定就用显示指定的, 没有就用变量名. 结果输出hello two! 就是对的了.
byType 显示指定
装配代码
其它代码不变 , 装配改为显示指定type值,如下
@Resource(type = HelloServiceImpl1.class )private HelloService helloServiceImpl1;public void say(){helloServiceImpl1.sayHello();}
这个变化就是上个示例中 指定了name属性的值
运行测试
hello one!
Process finished with exit code 0
分析
显示指定了type = HelloServiceImpl1.class , 也就范围就是 helloServiceImpl1 , 根据开头的灵魂总结 , type已经确定了一个 , 那么 name (默认变量名 或者显示指定 ) 的值 就必须是helloServiceImpl1 或者是一个在spring容器中找不到的名称.
注意: 这是个坑, 如果你指定的变量名刚好是spring容器中的某个bean的id , 那么这里就会报
Bean named ‘xxxx’ is expected to be of type ‘com.resource.service.impl.HelloServiceImpl1’ 的异常!!!
这里用代码演示下:
新建了个HiService类
package com.resource.service.impl;
@Component
public class HiService {public void sayHello() {System.out.println("Hi Hi!");}
}
装配类 (主要改了变量名为hiservice ,HiService 的bean id)
@Resource(type = HelloServiceImpl1.class )private HelloService hiService;public void say(){hiService.sayHello();}
运行报类型的错误如下:
org.springframework.beans.factory.BeanNotOfRequiredTypeException:Bean named 'hiService' is expected to be of type 'com.resource.service.impl.HelloServiceImpl1' but was actually of type 'com.resource.service.impl.HiService'
finally
以上仅为个人见解 , 能看到这里希望能让您有所收获.
抛砖引玉 , 如有不到之处, 敬请指正.
@Resource详解-代码示例相关推荐
- 加密系列 | 3DES加密和解密算法详解代码示例
3DES的在Java的实现与DES类似,如下代码为3DES加密算法.CBC模式.PKCS5Padding填充方式的加密解密结果,参考代码如下所示: import java.security.Key;i ...
- 百度PaddleOCR及云平台OCR API详解及示例
百度PaddleOCR及云平台OCR API详解及示例 目录 百度PaddleOCR及云平台OCR API详解及示例 使用百度开源的PaddleOCR 多个开源代码库比较
- 31.进程管理之进程概览,及ps命令详解,ps -ef,ps aux,ps -le,ps -l输出详解和示例
本小章讲解进程管理中的进程概览和作用,及ps命令详解,ps -ef,ps aux,ps -le,ps -l的输出详解和示例 文章目录 进程概览 什么是进程和程序 进程管理的作用 进程启动方式 僵尸进程 ...
- lammps输出MSD(均方根位移)详解及示例教程
[lammps第十五讲]lammps输出MSD(均方根位移)详解及示例教程 原创 一直陪着你的 LAMMPS交流站 2021-10-23 11:45 收录于话题 #lammps21个内容 #lammp ...
- Ehcache 中ehcache.xml 配置详解和示例
EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. Ehcache是一种广泛使用的开源Java分布式缓存.主要面向通用缓存 ...
- waitpid函数详解+应用示例
来源:微信公众号「编程学习基地」 文章目录 waitpid函数的使用 waitpid()函数定义 参数详解 使用示例 waitpid函数的使用 当用fork启动一个新的子进程的时候,子进程就有了新的生 ...
- Oracle创建表语句(Create table)语法详解及示例
Oracle创建表语句(Create table)语法详解及示例 创建表(Create table)语法详解 1. ORACLE常用的字段类型ORACLE常用的字段类型有 VARCHAR2 (si ...
- Math 的 ceil、floor、round方法详解及示例
Math 的 ceil.floor.round方法详解及示例 大家好,我是酷酷的韩~ 一.Math.ceil() ceil的英文意义是天花板,该方法就表示向上取整(取大),Math.ceil(9.1) ...
- MySQL隔离级别--未提交读,提交读,可重复读,序列化--详解(有示例)
原文网址:MySQL隔离级别--未提交读,提交读,可重复读,序列化--详解(有示例)_IT利刃出鞘的博客-CSDN博客 简介 本文介绍MySQL的事务隔离级别的含义,并用示例说明各个 ...
- BMP180气压传感器详解与示例(STM32 附带源码)
BMP180气压传感器详解与示例(STM32 附带源码) 简介 工作模式 校准数值 测试流程 第一步:微处理器读取校准数值 第二步:读取温度.气压初始值 第三步:计算温度.气压 第四步:计算海拔高度 ...
最新文章
- 在windows中创建一个影子用户
- Angular @Effect监听指定Action类型的实现原理
- python jieba词频统计英文文本_python实战,中文自然语言处理,应用jieba库来统计文本词频...
- Java中map关于putAll()和“=”的区别
- ajax注册用户名为空,怎么用ajax和js检测用户名是否合法和不能为空
- 手机号中间四位星号显示
- java 内部类_Java内部类总结
- 太强了!一个基于 Redis 的限流系统的设计!
- linux raw串口,linux下串口raw驱动(US100超声波)--Apple的学习笔记
- Docker容器实战(七) - 容器中进程视野下的文件系统
- secureCRT下载地址,亲测有效
- bp神经网络数字识别matlab_pytorch神经网络实践(1): 安装与初次使用pytorch搭建神经网络实践手写数字识别教程
- Python获取最新省市区列表并绘制中国地图(含港澳台)
- python安装pandas太慢_pytorch 安装缓慢 或者报错问题 pandas 安装
- snownlp抛出错误_网易云评论爬虫及情感分析
- 啤酒与尿布:数据分析相关性分析案例一
- java计算机毕业设计人口普查信息管理系统源代码+数据库+系统+lw文档
- 使用Eclipse创建Servlet
- Spring Boot 项目使用Spring Security防护CSRF攻击实战
- 服务器端渲染和客户端渲染有什么区别?
热门文章
- 统计学习之第三天(可汗学院公开课:统计学)
- 页面视觉稳定性之优化CLS
- python爬取在线视频思路,用python实现多线程爬取影视网站全部视频方法【笔记】...
- 360随身wifi3代linux驱动下载,360随身wifi3驱动-360随身wifi驱动下载 v5.3.0.5005官方版--pc6下载站...
- 论能逼疯一个人的nvidia显卡驱动在ubuntu16.04上的安装
- html页面大于号,css中大于号()是什么意思?
- python动态爬虫_Python动态网页爬虫技术
- 1.2GHz Atom处理器 诺基亚N9配置曝光
- 【数据结构练习题——查找】
- Siebel_CRM