专栏首页码匠的流水账聊聊spring cloud netflix ribbon的eager load

聊聊spring cloud netflix ribbon的eager load

本文主要研究一下spring cloud netflix ribbon的eager load

RibbonAutoConfiguration

spring-cloud-netflix-ribbon-2.1.1.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/RibbonAutoConfiguration.java

@Configuration
@Conditional(RibbonAutoConfiguration.RibbonClassesConditions.class)
@RibbonClients
@AutoConfigureAfter(name = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration")
@AutoConfigureBefore({ LoadBalancerAutoConfiguration.class,
AsyncLoadBalancerAutoConfiguration.class })
@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;
}

@Bean
@ConditionalOnMissingBean(LoadBalancerClient.class)
public LoadBalancerClient loadBalancerClient() {
return new RibbonLoadBalancerClient(springClientFactory());
}

@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();
}

@Bean
@ConditionalOnProperty("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;

@Bean
public RestTemplateCustomizer restTemplateCustomizer(
final RibbonClientHttpRequestFactory ribbonClientHttpRequestFactory) {
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
@Conditional(OnRibbonRestClientCondition.class)
@interface ConditionalOnRibbonRestClient {

}

private static class OnRibbonRestClientCondition extends AnyNestedCondition {

OnRibbonRestClientCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}

@Deprecated // remove in Edgware"
@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.
 */
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 {

}

}

}
  • RibbonAutoConfiguration启用了RibbonEagerLoadProperties、ServerIntrospectorProperties两个配置,这里主要是注册了SpringClientFactory,创建LoadBalancerClient、LoadBalancedRetryFactory、RibbonApplicationContextInitializer、RestTemplateCustomizer及RibbonClientHttpRequestFactory

RibbonApplicationContextInitializer

spring-cloud-netflix-ribbon-2.1.1.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/RibbonApplicationContextInitializer.java

public class RibbonApplicationContextInitializer
implements ApplicationListener<ApplicationReadyEvent> {

private final SpringClientFactory springClientFactory;

// List of Ribbon client names
private final List<String> clientNames;

public RibbonApplicationContextInitializer(SpringClientFactory springClientFactory,
List<String> clientNames) {
this.springClientFactory = springClientFactory;
this.clientNames = clientNames;
}

protected void initialize() {
if (clientNames != null) {
for (String clientName : clientNames) {
this.springClientFactory.getContext(clientName);
}
}
}

@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
initialize();
}

}
  • RibbonApplicationContextInitializer实现了ApplicationListener接口,其响应ApplicationReadyEvent事件执行initialize操作,这里主要是挨个对配置的clientNames执行springClientFactory.getContext(clientName)操作

SpringClientFactory

spring-cloud-netflix-ribbon-2.1.1.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/SpringClientFactory.java

public class SpringClientFactory extends NamedContextFactory<RibbonClientSpecification> {
//......

protected AnnotationConfigApplicationContext getContext(String name) {
return super.getContext(name);
}

//......
}
  • SpringClientFactory的getContext方法调用了父类NamedContextFactory的getContext

NamedContextFactory

spring-cloud-context-2.2.0.M1-sources.jar!/org/springframework/cloud/context/named/NamedContextFactory.java

public abstract class NamedContextFactory<C extends NamedContextFactory.Specification>
implements DisposableBean, ApplicationContextAware {

//......

protected AnnotationConfigApplicationContext getContext(String name) {
if (!this.contexts.containsKey(name)) {
synchronized (this.contexts) {
if (!this.contexts.containsKey(name)) {
this.contexts.put(name, createContext(name));
}
}
}
return this.contexts.get(name);
}

protected AnnotationConfigApplicationContext createContext(String name) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
if (this.configurations.containsKey(name)) {
for (Class<?> configuration : this.configurations.get(name)
.getConfiguration()) {
context.register(configuration);
}
}
for (Map.Entry<String, C> entry : this.configurations.entrySet()) {
if (entry.getKey().startsWith("default.")) {
for (Class<?> configuration : entry.getValue().getConfiguration()) {
context.register(configuration);
}
}
}
context.register(PropertyPlaceholderAutoConfiguration.class,
this.defaultConfigType);
context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(
this.propertySourceName,
Collections.<String, Object>singletonMap(this.propertyName, name)));
if (this.parent != null) {
// Uses Environment from parent as well as beans
context.setParent(this.parent);
// jdk11 issue
// https://github.com/spring-cloud/spring-cloud-netflix/issues/3101
context.setClassLoader(this.parent.getClassLoader());
}
context.setDisplayName(generateDisplayName(name));
context.refresh();
return context;
}

//......
}
  • NamedContextFactory的getContext主要是返回或者创建AnnotationConfigApplicationContext

小结

  • RibbonAutoConfiguration启用了RibbonEagerLoadProperties、ServerIntrospectorProperties两个配置,这里主要是注册了SpringClientFactory,创建LoadBalancerClient、LoadBalancedRetryFactory、RibbonApplicationContextInitializer、RestTemplateCustomizer及RibbonClientHttpRequestFactory
  • RibbonApplicationContextInitializer实现了ApplicationListener接口,其响应ApplicationReadyEvent事件执行initialize操作,这里主要是挨个对配置的clientNames执行springClientFactory.getContext(clientName)操作
  • SpringClientFactory的getContext方法调用了父类NamedContextFactory的getContext;NamedContextFactory的getContext主要是返回或者创建AnnotationConfigApplicationContext

doc

  • RibbonClientConfiguration

本文分享自微信公众号 - 码匠的流水账(geek_luandun),作者:码匠乱炖

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-07-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 聊聊spring cloud netflix ribbon的eager load

    本文主要研究一下spring cloud netflix ribbon的eager load

    codecraft
  • 聊聊spring cloud的consulRetryInterceptor

    本文主要研究一下spring cloud的consulRetryInterceptor

    codecraft
  • 聊聊spring cloud的FeignClientFactoryBean

    本文主要研究一下spring cloud的FeignClientFactoryBean

    codecraft
  • 聊聊spring cloud netflix ribbon的eager load

    本文主要研究一下spring cloud netflix ribbon的eager load

    codecraft
  • react的事件处理为什么要bind this 改变this的指向?

    这句话大概意思就是,你要小心jax回调函数里面的this,class方法默认是不会绑定它的

    Tz一号
  • 七夕最污代码,单身慎入

    2.找不到对象说爱(Fatal error: Call to a member function on a non-object), 他怎么才能说出爱?

    后端技术探索
  • springboot之mvc原理(二)-能力支持

    前边一篇文章《springboot之mvc原理(一)-请求处理》我们详细分析了springboot应用接收http请求的处理过程,那么进一步的思考一下,...

    Typhoon
  • React 深入系列5:事件处理

    iKcamp
  • 面向对象版tab 栏切换案例

    梨涡浅笑
  • PHP设计模式——抽象方法

    Dragon公司的业务受到轰炸,而CEO希望特许所有海外分支机构的专营权。他首先要注意的问题是如何确保产品质量。他们不希望特许经营者削减成本和使用低质量的组件。...

    Lemon黄

扫码关注云+社区

领取腾讯云代金券