SpringCloud中@Resource注入DiscoveryClient为何选EurekaDiscoveryClient
@Resource注入EurekaDiscoveryClient的核心原因
首先明确场景:org.springframework.cloud.client.discovery.DiscoveryClient是Spring Cloud抽象的服务发现顶层接口,不同注册中心(Eureka、Consul、Nacos、Zookeeper等)都有对应的实现类,示例注入代码如下:
@Resource private DiscoveryClient discoveryClient; public void getServerPort(){ List<ServiceInstance> serviceInstances = discoveryClient.getInstances("PROVIDER-PAYMENT"); // 省略后续业务逻辑 }
最终注入Eureka实现而非其他实现,是两个机制共同作用的结果:
- 第一是
@Resource本身的匹配逻辑@Resource是JSR-250规范定义的注入注解,默认优先按字段名匹配容器中的Bean,匹配失败才会退化为按类型匹配。当前字段名是discoveryClient,各注册中心的实现Bean默认不会使用这个名称注册,所以直接走按类型匹配逻辑。 - 第二是Spring Cloud自动装配的Bean优先级规则
Spring Boot的自动装配是按依赖条件生效的:- 只要项目中引入了Eureka客户端依赖(
spring-cloud-starter-netflix-eureka-client),Eureka对应的自动配置类就会满足生效条件,向容器中注册EurekaDiscoveryClient实例,并且给这个实例打上@Primary注解,标记为同类型Bean的优先注入选项。 - 其他DiscoveryClient实现类,只要没引入对应注册中心的客户端依赖,对应自动配置类根本不会触发,不会往容器中注册对应的Bean,自然不会被选中。
- 就算因为依赖传递把其他实现类带入了项目,只要当前激活的注册中心是Eureka,其他实现类要么不会被注册为Bean,要么不会被标记为@Primary,按类型注入时Spring会优先选择带@Primary注解的Eureka实现。
- 只要项目中引入了Eureka客户端依赖(
注意:如果项目中同时引入了多个注册中心的客户端依赖且没有做依赖排除,可能出现同类型下多个Bean都存在、且没有明确@Primary的情况,此时注入会抛出
NoUniqueBeanDefinitionException异常,需要手动通过@Resource(name="xxx")指定Bean名称,或者配合@Qualifier明确要注入的实现。
内容的提问来源于stack exchange,提问作者ApplePie
相关产品推荐
相关产品推荐

