Ribbon(五) Ribbon源码分析- Ribbon客户端是如何加载的

it2023-05-22  69

1. @RibbonClient注解:   此注解可以实现Ribbon客户端,ribbon需要设置客户端的名称,以及相关的路由配置类. 

  以下是启用Ribbon客户端的代码:

@SpringBootApplication //指定这个新的负载算法类给 MICROSERVICE-PROVIDER-PRODUCT 这个服务用 //这里的name 是服务的名称,如果需要有多个服务提供方,这个时候可以使用@RibbonClients进行配置 @RibbonClient(name = "MICROSERVICE-PROVIDER-PRODUCT", configuration = RibbonConfig.class) public class ConsumerRibbonApp { public static void main(String[] args) { SpringApplication.run(ConsumerRibbonApp.class, args); } }

@RibbonClient的注解源码:

@Configuration @Import(RibbonClientConfigurationRegistrar.class) //重要的类 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RibbonClient { String value() default ""; String name() default ""; // value和name是等价了,用于设置客户端的实例名称,而configuration用于指定配置类 Class<?>[] configuration() default {}; }

      在上面的源码中,它导入了个RibbonClientConfigurationRegistrar,他实现了ImportBeanDefinitionRegistrar(此接口仅位于org.springframework.context.annotation包下),他也不用多说,是spring的工具接口,用于spring动态注册BeanDefinition的接口,在这是用于注册Ribbon所需的BeanDefinition(比如Ribbon客户端实例 org.springframework.cloud.netflix.ribbon.RibbonClientConfigurationRegistrar#registerBeanDefinitions). 所以在这里,是借助了Spring的方法将RibbonClient注册进来.  

     下面重点来查看一下RibbonClientConfigurationRegistrar中实现的  registerBeanDefinitions()方法. 

@Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { //获取@RibbonClient的参数,获取clientName后进行configuraction注册 // 上面的设置的参数为 @RibbonClient(name = "MICROSERVICE-PROVIDER-PRODUCT", configuration = RibbonConfig.class) Map<String, Object> attrs = metadata .getAnnotationAttributes(RibbonClients.class.getName(), true); if (attrs != null && attrs.containsKey("value")) { AnnotationAttributes[] clients = (AnnotationAttributes[]) attrs.get("value"); for (AnnotationAttributes client : clients) { registerClientConfiguration(registry, getClientName(client), client.get("configuration")); //注册 } } if (attrs != null && attrs.containsKey("defaultConfiguration")) { String name; if (metadata.hasEnclosingClass()) { name = "default." + metadata.getEnclosingClassName(); } else { name = "default." + metadata.getClassName(); } registerClientConfiguration(registry, name, attrs.get("defaultConfiguration")); //注册 } Map<String, Object> client = metadata .getAnnotationAttributes(RibbonClient.class.getName(), true); String name = getClientName(client); // 获取 name或value值 if (name != null) { registerClientConfiguration(registry, name, client.get("configuration")); //注册 } }

实现注册的方法调用的是 registerClientConfiguration,   它会注册一个RibbonClientSpecification的bean,名称是ribbon的名称加上.RibbonClientSpecification下面看源码: 

private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object configuration) { BeanDefinitionBuilder builder = BeanDefinitionBuilder .genericBeanDefinition(RibbonClientSpecification.class); builder.addConstructorArgValue(name); builder.addConstructorArgValue(configuration); registry.registerBeanDefinition(name + ".RibbonClientSpecification", builder.getBeanDefinition()); }

   在上面源码中出现的RibbonClientSpecification 实现了 NamedContextFactory.Specification,是提供给SpringClientFactory使用的,他用于初始化ribbon的相关实例.   

    那么SpringClientFactory这个类位于哪呢? 请查看  spring-cloud-netflix-ribbon-xxx.jar下的 spring.factories配置文件中有

 

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration

它在org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration 这个类中(这就是ribbon的自动化配置类,它负责实始化ribbon中相关的Bean),那么SpringClientFactory在这里有初始化吗?

@Bean public SpringClientFactory springClientFactory() { SpringClientFactory factory = new SpringClientFactory(); factory.setConfigurations(this.configurations); //设置配置信息 return factory; //创建好SpringClientFactory后,可以给后面的LoadBalancerClient的Bean使用了. } @Bean @ConditionalOnMissingBean(LoadBalancerClient.class) public LoadBalancerClient loadBalancerClient() { return new RibbonLoadBalancerClient( springClientFactory() ); }

  那么最重要的就回到了LoadBalancerClient ,他是Ribbon项目最核心的类org.springframework.cloud.client.loadbalancer.LoadBalancerClient,   即客户端的负载均衡实现类.  这就回到了  Ribbon(三) Ribbon源码分析-负载均衡是如何通过@LoadBalanced 自动配置上去的   . 

 

 

最新回复(0)