根据如上逻辑可以看出会从3个地方将Ribbon相关的Configuration配置类注册到专门为其准备的ApplicationContext上下文,并根据配置类创建Ribbon核心接口的实现类,即达到配置RibbonClient的目的
从configurations这个Map中根据RibbonClient name获取专门为其指定的configuration配置类,并注册到其对应的ApplicationContext上下文
从configurations这个Map中找到 default. 开头 的配置类,即为所有RibbonClient的默认配置,并注册到其对应的ApplicationContext上下文
如果不是开发者单独指定的话,前两项都是没有数据的,还会注册Spring Cloud的默认配置类RibbonClientConfiguration
那么configurations这个Map里的配置类数据是从哪儿来的呢??下面逐步分析
//## RibbonAutoConfiguration @Autowired(required = false) private List<RibbonClientSpecification> configurations = new ArrayList<>(); @Bean public SpringClientFactory springClientFactory() { SpringClientFactory factory = new SpringClientFactory(); factory.setConfigurations(this.configurations); return factory; }首先是在RibbonAutoConfiguration自动配置类创建SpringClientFactory是设置的,这个configurations集合是@Autowired的Spring容器内的RibbonClientSpecification集合,那么RibbonClientSpecification集合是何时被注册的??
//## org.springframework.cloud.netflix.ribbon.RibbonClientConfigurationRegistrar public class RibbonClientConfigurationRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { // 1、@RibbonClients注解 Map<String, Object> attrs = metadata.getAnnotationAttributes( RibbonClients.class.getName(), true); // 1.1 value是RibbonClient[],遍历针对具体的RibbonClient配置的configuration配置类,并注册 if (attrs != null && attrs.containsKey("value")) { AnnotationAttributes[] clients = (AnnotationAttributes[]) attrs.get("value"); for (AnnotationAttributes client : clients) { registerClientConfiguration(registry, getClientName(client), client.get("configuration")); } } // 1.2 找到@RibbonClients注解的defaultConfiguration,即默认配置 // 注册成以default.Classname.RibbonClientSpecification为名的RibbonClientSpecification 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")); } // 2、@RibbonClient注解 // 注册某个具体Ribbon Client的configuration配置类 Map<String, Object> client = metadata.getAnnotationAttributes( RibbonClient.class.getName(), true); String name = getClientName(client); if (name != null) { registerClientConfiguration(registry, name, client.get("configuration")); } } private String getClientName(Map<String, Object> client) { if (client == null) { return null; } String value = (String) client.get("value"); if (!StringUtils.hasText(value)) { value = (String) client.get("name"); } if (StringUtils.hasText(value)) { return value; } throw new IllegalStateException( "Either 'name' or 'value' must be provided in @RibbonClient"); } 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()); } }如上可知,configurations配置类集合是根据@RibbonClient 和 @RibbonClients 注解配置的,分别有 针对具体某个RibbonClient的配置 和 default默认配置
总结一下,Ribbon相关的@Configuration配置类是如何加载的
在创建完RibbonClient对应的AnnotationConfigApplicationContext后,先从根据@RibbonClient 和 @RibbonClients 注解加载的configurations集合中找当前RibbonClient name对应的配置类,如有,就注册到上下文
再从configurations集合中找根据@RibbonClients注解加载的 default.开头 的默认配置类,如有,就注册到上下文
最后注册Spring Cloud默认的 RibbonClientConfiguration
上面说是如何创建RibbonClient相关的ApplicationContext上下文及注册Ribbon Client相关的配置类的逻辑,在确定配置类后,其中会用到Ribbon的IClientConfig相关的客户端配置来加载Ribbon客户端相关的配置信息,如超时配置、具体创建哪个核心接口的实现类等,可以从Spring Cloud默认注册的 RibbonClientConfiguration来一探究竟