如何理解@Resource和@Reference的区别
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何理解@Resource和@Reference的区别相关的知识,希望对你有一定的参考价值。
参考技术A 1,定义:@Resource:spring的注解,作用:spring中获取已经注入到spring中的Bean
@Reference: dubbo的注解,作用:注入duboo服务的对象
2,遇到问题:
本地配置:
报错:No provider available from registry **** for service ------------
哇,经典报错,一看错误就以为是生产者没有启动喽,去zk上面看dubbo生产者情况,真的没有,问题好像已经找到了,,等等,忽然发现他为什么去的是 registry 1呢,不应该去1和2都找吗? 对了,@Reference 注册dubbo不管是什么方式,无非是registry 和 version等指定,由于我没有指定,那按照spring的理解肯定是走自动装配喽,那我这边配置了两个注册中心,是不是他会智能的都找找呢?(不是的,dubbo生产者如果指定多个registry,然后<dubbo:service/>声明的服务会注册到多个注册中心,<dubbo:reference/>消费端多注册中心时是需要指定去哪个注册中心的)我不想在@Reference后面写一大堆,就想走自动化装配,最后找到可以在registry声明时 default 的属性的,
根据一系列的猜测、我把配置改为了:
自此问题解决了,,,,,
我发现新的问题:使用@Reference来注入dubbo服务,那如果我项目中多个地方想使用,我在多个类中使用@Reference ,岂不是注入多个bean了(这个理解是有问题的,这时未意识到)。这显然是有问题的,因此我想将dubbo服务以单例注入到spring中,换成 spring自己的@Resource标签来获取,因此我将配置改成了一下:
测试一下:确实好使,,自此配置使用方面没什么问题了,符合一个人的正常逻辑了,
但是还有一个问题,就是:
“我发现新的问题:使用@Reference来注入dubbo服务,那如果我项目中多个地方想使用,我在多个类中使用@Reference ,岂不是注入多个bean了 ” 这个问题真的存在吗?
下面来解答这个问题:
spring的配置 使用 xml 或者注解 只是 使用方式的不同,@Reference 和 <dubbo:reference/> 的效果应该是是一样的, spring默认注入Bean,scope应该是singleton , 那我在多个类中使用@Reference 注入同一个dubbo服务应该是在spring中只存在一个了,,事实上的是的,
多个@Reference 标签 注入配置信息完全相同的 服务 ,是会有服务Bean缓存的,保证只会有一个 服务Bean ,源码如下: 这个方法 generateReferenceBeanCacheKey 是缓存key的获取。。
private ReferenceBean<?> buildReferenceBean(Reference reference, Class<?> referenceClass) throws Exception // 获取服务引用对象的缓存key String referenceBeanCacheKey = generateReferenceBeanCacheKey(reference, referenceClass); // 从缓存map中获取服务引用对象 ReferenceBean<?> referenceBean = referenceBeansCache.get(referenceBeanCacheKey); if (referenceBean == null) // 如果引用对象为空,则需要当场创建一个 ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder .create(reference, classLoader, applicationContext) .interfaceClass(referenceClass); referenceBean = beanBuilder.build(); //并且放入到缓存map中。 referenceBeansCache.putIfAbsent(referenceBeanCacheKey, referenceBean); return referenceBean; private String generateReferenceBeanCacheKey(Reference reference, Class<?> beanClass) // 获取接口名称 String interfaceName = resolveInterfaceName(reference, beanClass); // 通过引用的URl+接口名+接口版本号+接口分组,用来做缓存key String key = reference.url() + "/" + interfaceName + "/" + reference.version() + "/" + reference.group(); Environment environment = applicationContext.getEnvironment(); key = environment.resolvePlaceholders(key); return key;
自此问题说明完毕。。
问题整理:
1,多注册中心时,spring 自动化装配时,需要自己指定 某一个注册中心 或者 将某个注册中心 default设置为true.
2, @Resource 和 @Reference 都可 注入 dubbo服务但是 概念是不一样的。
3,@Reference 注解可以在多个类中注入 相同服务Bean 不会造成服务Bean 存在多个。。
注:源码参考 文章 https://shared-code.com/article/121
@reference和@resource的区别
参考技术A @reference是dubbo注解,@resource是spring 注解。@resource作用相当于@Autowired,只不过@Autowired是 byType 自动注入,而@Resource默认 byName 自动注入。
@Reference是dubbo的注解,也是注入,但是一般用来注入分布式的远程服务对象,需要配合dubbo配置使用。
@reference和@resource的区别就是@resource是本地spring容器,@reference是把远程服务对象当做spring容器中的对象一样注入。
以上是关于如何理解@Resource和@Reference的区别的主要内容,如果未能解决你的问题,请参考以下文章
How do I duplicate a resource reference in code behind in WPF?
解决问题 inner element must either be a resource reference or empty.