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 自动配置上去的 .