发布于2021-06-12 14:13 阅读(472) 评论(0) 点赞(9) 收藏(5)
在springboot的自动装配原理上,我们知道要使用一个组件,那么先去找spring.factories
,所以这里我们直接开始看spring-cloud-netflix-ribbon-2.1.0
的spring.factories
文件
@Configuration
// 这个是判断条件的集合,只有RibbonClassesConditions里面的条件都满足了才能实例化这个配置类
// 到spring 容器中去
@Conditional(RibbonAutoConfiguration.RibbonClassesConditions.class)
// 这个主要是为了注入RibbonClientConfigurationRegistrar,这个类后面详细解析一下
@RibbonClients
// 这个意思就是eureka client 装配完成后,才会装配Ribbon。这是因为ribbon要依赖eureka
@AutoConfigureAfter(name = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration")
/// 在ribbon自动装配完后,继续装配LoadBalancerAutoConfiguration 和AsyncLoadBalancerAutoConfiguration
// 这两个类挺核心的,后面详细讲讲
@AutoConfigureBefore({LoadBalancerAutoConfiguration.class, AsyncLoadBalancerAutoConfiguration.class})
// 从spring的配置文件中读取配置信息到指定类中
@EnableConfigurationProperties({RibbonEagerLoadProperties.class, ServerIntrospectorProperties.class})
public class RibbonAutoConfiguration {
@Autowired(required = false)
private List<RibbonClientSpecification> configurations = new ArrayList<>();
@Autowired
private RibbonEagerLoadProperties ribbonEagerLoadProperties;
@Bean
public HasFeatures ribbonFeature() {
return HasFeatures.namedFeature("Ribbon", Ribbon.class);
}
@Bean
public SpringClientFactory springClientFactory() {
SpringClientFactory factory = new SpringClientFactory();
factory.setConfigurations(this.configurations);
return factory;
}
// 创建ribbon负载均衡器客户端
@Bean
@ConditionalOnMissingBean(LoadBalancerClient.class)
public LoadBalancerClient loadBalancerClient() {
return new RibbonLoadBalancerClient(springClientFactory());
}
// 创建重试型ribbon 负载均衡器生产工厂
// 存在两种发消息的工具,一种是RestTemplate,还有一种是RetryTemplate
// 针对不同的需求,去创建不同的负载均衡器工厂
@Bean
@ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate")
@ConditionalOnMissingBean
public LoadBalancedRetryFactory loadBalancedRetryPolicyFactory(final SpringClientFactory clientFactory) {
return new RibbonLoadBalancedRetryFactory(clientFactory);
}
@Bean
@ConditionalOnMissingBean
public PropertiesFactory propertiesFactory() {
return new PropertiesFactory();
}
// 饿汉式加载 ribbon client
@Bean
@ConditionalOnProperty(value = "ribbon.eager-load.enabled")
public RibbonApplicationContextInitializer ribbonApplicationContextInitializer() {
return new RibbonApplicationContextInitializer(springClientFactory(),
ribbonEagerLoadProperties.getClients());
}
@Configuration
@ConditionalOnClass(HttpRequest.class)
@ConditionalOnRibbonRestClient // 这个就在下面有定义
protected static class RibbonClientHttpRequestFactoryConfiguration {
@Autowired
private SpringClientFactory springClientFactory;
// restTemplate 定制化器
@Bean
public RestTemplateCustomizer restTemplateCustomizer(
final RibbonClientHttpRequestFactory ribbonClientHttpRequestFactory) {
// 设置为RibbonClientHttpRequestFactory 创建restTemplate
return restTemplate -> restTemplate.setRequestFactory(ribbonClientHttpRequestFactory);
}
@Bean
public RibbonClientHttpRequestFactory ribbonClientHttpRequestFactory() {
return new RibbonClientHttpRequestFactory(this.springClientFactory);
}
}
//TODO: support for autoconfiguring restemplate to use apache http client or okhttp
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
// ribbon.http.client.enabled 判断是否开启ribbon.http.client.enabled 这个是zuul使用的
// ribbon.restclient.enabled 判断是否开启ribbon.restclient.enabled 这个是ribbon使用的
@Conditional(OnRibbonRestClientCondition.class)
@interface ConditionalOnRibbonRestClient { }
// 加载条件集合
private static class OnRibbonRestClientCondition extends AnyNestedCondition {
public OnRibbonRestClientCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@Deprecated
@ConditionalOnProperty("ribbon.http.client.enabled")
static class ZuulProperty {}
@ConditionalOnProperty("ribbon.restclient.enabled")
static class RibbonProperty {}
}
/**
* {@link AllNestedConditions} that checks that either multiple classes are present
* 当下面多个条件都满足的情况下,才会加载ribbon
*/
static class RibbonClassesConditions extends AllNestedConditions {
RibbonClassesConditions() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
}
@ConditionalOnClass(IClient.class)
static class IClientPresent {
}
@ConditionalOnClass(RestTemplate.class)
static class RestTemplatePresent {
}
@ConditionalOnClass(AsyncRestTemplate.class)
static class AsyncRestTemplatePresent {
}
@ConditionalOnClass(Ribbon.class)
static class RibbonPresent {
}
}
}
上面源码总结有以下几点:
1.从 @AutoConfigureAfter(name = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration")
注解发现RibbonAutoConfiguration
是依赖于EurekaClientAutoConfiguration
的。
2. LoadBalancerAutoConfiguration
和 AsyncLoadBalancerAutoConfiguration
这两个类在后面装配,说明需要依赖RibbonAutoConfiguration
创建的东西
3. RibbonClassesConditions
是RibbonAutoConfiguration
装配的前提条件,里面是多个条件的集合
4. SpringClientFactory
这个工厂类是用于创建ribbon client 客户端,load balancer 负载均衡器,客户端配置实例对象的。
5. 创建了一个持有springClientFactory
对象的负载均衡器客户端LoadBalancerClient
6.LoadBalancedRetryFactory
如果开启重试功能,那么需要创建一个负责创建重试负载均衡器的工厂。
7.RibbonApplicationContextInitializer
ribbon client 饿汉式加载。就是启动完就把ribbon client全部 初始化好
8. RibbonClientHttpRequestFactoryConfiguration
这个做了两件事,
第一个通过RestTemplateCustomizer
定制化了RestTemplate
,
第二个初始化定制RestTemplate
的工厂RibbonClientHttpRequestFactory
1.restTemplate 作为spring cloud feign的通讯工具,在这里会被特殊处理来达到负载均衡的目的
@LoadBalanced // 注解标记这些restTemplate 会使用负载均衡客户端
@Autowired(required = false) // RestTemplate 自动注入
private List<RestTemplate> restTemplates = Collections.emptyList();
2.定制化RestTemplate集合,主要是为每个restTemplate注入ribbon的factory。
// 这里对restTemplates 进行多个定制化器处理
@Bean
public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
return () -> restTemplateCustomizers.ifAvailable(customizers -> {
for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
for (RestTemplateCustomizer customizer : customizers) {
customizer.customize(restTemplate);
}
}
});
}
3.负载均衡请求转化器
// http请求中加上服务实例信息
@Autowired(required = false)
private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();
// 负载均衡器工厂
// 负责为LoadBalancerInterceptor和RetryLoadBalancerInterceptor创建LoadBalanceRequest
// 应用LoadBalancerRequestTransformer 请求转换器到被拦截的HttpRequest请求中去。
@Bean
@ConditionalOnMissingBean
public LoadBalancerRequestFactory loadBalancerRequestFactory(
LoadBalancerClient loadBalancerClient) {
return new LoadBalancerRequestFactory(loadBalancerClient, transformers);
}
5.LoadBalancerInterceptorConfig 负载均衡器的拦截器配置
// 创建负载均衡拦截器
@Bean
public LoadBalancerInterceptor ribbonInterceptor(
LoadBalancerClient loadBalancerClient,
LoadBalancerRequestFactory requestFactory) {
return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
}
// 构建一个restTemplate定制化器
// 将拦截器加载到每个restTemplate上去
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(
final LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(
restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
};
}
这篇文章主要为后面几篇做一个铺垫,知道有些东西在哪初始化,配置了哪些东西。看源码,我觉还是不要先死扣细节和那些类的具体作用。先基本了解一下ribbon运行需要哪些前置的东西,然后再去看看ribbon的主流程,最后进行细节深入。
原文链接:https://blog.csdn.net/yang131peng/article/details/117784439
作者:怎么没有鱼儿上钩呢
链接:http://www.javaheidong.com/blog/article/222170/a1f16afef7ee43b3b353/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!