spring clound负载均衡之Ribbon(二)- 自动装配

在之前的文章spring cloud负载均衡之ribbon—demo实现  通过demo的方式实现了ribbon的使用,在这个实例中,通过round robin的方法轮询访问远程依赖的服务列表,达到负载均衡的方式。在这边文章中,主要介绍ribbon自动装配的过程,以及在装配过程中比较重要的类型,让我们对ribbon有一个整体的设计概念,便于后面我们对ribbon的学习。

前情回顾

spring cloud负载均衡之ribbon—demo实现 中,我们在创建RestTemplate的时候, 使用了@LoadBalanced注解标记了bean,具体代码如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@LoadBalanced @Bean public RestTemplate restTemplate() { return new RestTemplate(); }
@LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

在这段代码中,涉及到了两个类型,第一个就是@LoadBalanced注解以及RestTemplate类型,这两个类在远程访问中充当了比较重要的角色,我们一一来看下。

@LoadBalanced

这个注解标记了访问远程http请求时,需要采用负载均衡的方式发送请求,我们看下该注解的源码:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/**
* Annotation to mark a RestTemplate bean to be configured to use a LoadBalancerClient.
* @author Spencer Gibb
*/
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier
public @interface LoadBalanced {
}
/** * Annotation to mark a RestTemplate bean to be configured to use a LoadBalancerClient. * @author Spencer Gibb */ @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Qualifier public @interface LoadBalanced { }
/**
 * Annotation to mark a RestTemplate bean to be configured to use a LoadBalancerClient.
 * @author Spencer Gibb
 */
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier
public @interface LoadBalanced {

}

在这个注解的实现中,有两个需要注意的点:

  • 根据该类的注释,该注解主要是用于标记RestTemplate bean并且用于使用LoadBalancerClient, 因此可以知道,该注解的使用其实是有使用的限制
  • 该注解是一个派生的注解,被@Qualifier注解修饰。

@Qualifier

在我们常用的场景中,我们一般配合@Autowired注解使用,根据名称获取满足条件的bean, 但是在这里该注解还有一个用法,用于实现自定义注解。具体源码如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/**
* This annotation may be used on a field or parameter as a qualifier for
* candidate beans when autowiring. It may also be used to annotate other
* custom annotations that can then in turn be used as qualifiers.
*
* @author Mark Fisher
* @author Juergen Hoeller
* @since 2.5
* @see Autowired
*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
String value() default "";
}
/** * This annotation may be used on a field or parameter as a qualifier for * candidate beans when autowiring. It may also be used to annotate other * custom annotations that can then in turn be used as qualifiers. * * @author Mark Fisher * @author Juergen Hoeller * @since 2.5 * @see Autowired */ @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Qualifier { String value() default ""; }
/**
 * This annotation may be used on a field or parameter as a qualifier for
 * candidate beans when autowiring. It may also be used to annotate other
 * custom annotations that can then in turn be used as qualifiers.
 *
 * @author Mark Fisher
 * @author Juergen Hoeller
 * @since 2.5
 * @see Autowired
 */
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {

    String value() default "";

}

通过源码可以得知,该注解的另外一个用于就是自定义注解,自动注入满足自定义注解的bean类型。

LoadBalancerClient

在上面介绍@LoadBalanced注解时有介绍到,会涉及到LoadBalancerClient类,该类是一个接口定义, 由spring-cloud-commons实现, 其实就是抽象微服务部分的抽象属性,便于对接不同的微服务组件。具体源码如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public interface LoadBalancerClient extends ServiceInstanceChooser {
<T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;
<T> T execute(String serviceId, ServiceInstance serviceInstance,
LoadBalancerRequest<T> request) throws IOException;
URI reconstructURI(ServiceInstance instance, URI original);
}
public interface LoadBalancerClient extends ServiceInstanceChooser { <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException; <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException; URI reconstructURI(ServiceInstance instance, URI original); }
public interface LoadBalancerClient extends ServiceInstanceChooser {

    <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;

    <T> T execute(String serviceId, ServiceInstance serviceInstance,
            LoadBalancerRequest<T> request) throws IOException;

    URI reconstructURI(ServiceInstance instance, URI original);

}

RibbonAutoConfiguration

在ribbon加载并配置时,一般都需要查看spring.factories文件,具体配置如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration

可以知道自动加载配置时,会通过RibbonAutoConfiguration类进行ribbon的基本配置,因此我们直接查看该类源码即可。

加载条件

加载条件一般是通过类上的注解信息进行标注,因此我们优先查看该类上的注解列表,查看该类配置需要满足条件,以及加载顺序。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Configuration
@Conditional(RibbonAutoConfiguration.RibbonClassesConditions.class)
@RibbonClients
@AutoConfigureAfter(name = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration")
@AutoConfigureBefore({ LoadBalancerAutoConfiguration.class,AsyncLoadBalancerAutoConfiguration.class })
@EnableConfigurationProperties({ RibbonEagerLoadProperties.class, ServerIntrospectorProperties.class })
@Configuration @Conditional(RibbonAutoConfiguration.RibbonClassesConditions.class) @RibbonClients @AutoConfigureAfter(name = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration") @AutoConfigureBefore({ LoadBalancerAutoConfiguration.class,AsyncLoadBalancerAutoConfiguration.class }) @EnableConfigurationProperties({ RibbonEagerLoadProperties.class, ServerIntrospectorProperties.class })
@Configuration
@Conditional(RibbonAutoConfiguration.RibbonClassesConditions.class)
@RibbonClients
@AutoConfigureAfter(name = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration")
@AutoConfigureBefore({ LoadBalancerAutoConfiguration.class,AsyncLoadBalancerAutoConfiguration.class })
@EnableConfigurationProperties({ RibbonEagerLoadProperties.class, ServerIntrospectorProperties.class })

该注解列表可以表达一下几个信息:

  • 该类被加载,需要在classpath中找到RibbonClassesConditions
  • 该配置需要在EurekaClientAutoConfiguration配置之后执行配置
  • 当前配置完成后,需要配置LoadBalancerAutoConfigurationAsyncLoadBalancerAutoConfiguration
  • 加载并初始化配置RibbonEagerLoadPropertiesServerIntrospectorProperties

配置类加载

通过以上配置可以得知, 需要加载两个配置类型,分别为RibbonEagerLoadPropertiesServerIntrospectorProperties

RibbonEagerLoadProperties

查看该配置类型的源码:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@ConfigurationProperties(prefix = "ribbon.eager-load")
public class RibbonEagerLoadProperties {
private boolean enabled = false;
private List<String> clients;
}
@ConfigurationProperties(prefix = "ribbon.eager-load") public class RibbonEagerLoadProperties { private boolean enabled = false; private List<String> clients; }
@ConfigurationProperties(prefix = "ribbon.eager-load")
public class RibbonEagerLoadProperties {

    private boolean enabled = false;

    private List<String> clients;
}

该配置类主要保存以ribbon.eager-load.*相关的配置,配置总结如下:

配置 默认值 说明
ribbon.eager-load.enabled false 是否开启ribbon实时加载
ribbon.eager-load.clients null ribbon实时记载客户端列表

ServerIntrospectorProperties

查看该类源码如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@ConfigurationProperties("ribbon")
public class ServerIntrospectorProperties {
private List<Integer> securePorts = Arrays.asList(443, 8443);
public List<Integer> getSecurePorts() {
return securePorts;
}
public void setSecurePorts(List<Integer> securePorts) {
this.securePorts = securePorts;
}
}
@ConfigurationProperties("ribbon") public class ServerIntrospectorProperties { private List<Integer> securePorts = Arrays.asList(443, 8443); public List<Integer> getSecurePorts() { return securePorts; } public void setSecurePorts(List<Integer> securePorts) { this.securePorts = securePorts; } }
@ConfigurationProperties("ribbon")
public class ServerIntrospectorProperties {

    private List<Integer> securePorts = Arrays.asList(443, 8443);

    public List<Integer> getSecurePorts() {
        return securePorts;
    }

    public void setSecurePorts(List<Integer> securePorts) {
        this.securePorts = securePorts;
    }
}

该配置类主要用于保存以ribbon.*相关的配置信息,但是从源码角度查看,该类实际只是保存了ribbon.secure-ports列表列表,该配置默认值为[443, 8443]

配置中

当以上条件都满足后, 并且配置类型加载完成,则会进入RibbonAutoConfiguration类型的正式配置阶段。EurekaClientAutoConfiguation配置可以参考spring cloud 服务发现之Eureka Client(二)—自动装配

在配置过程中,主要涉及到基本比较重要的类型,其中包括SpringClientFactoryLoadBalancerClientLoadBalancedRetryFactoryPropertiesFactoryRestTemplateCustomizerRibbonApplicationContextInitilizer. 具体源码如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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);
}
// 创建SpringClientFactory对象
@Bean
public SpringClientFactory springClientFactory() {
SpringClientFactory factory = new SpringClientFactory();
factory.setConfigurations(this.configurations);
return factory;
}
// 当LoadBalancerClient对象不存在时,创建LoadBalancerClient对象
@Bean
@ConditionalOnMissingBean(LoadBalancerClient.class)
public LoadBalancerClient loadBalancerClient() {
return new RibbonLoadBalancerClient(springClientFactory());
}
// 判断classpath中是否包含了RetryTemplate类,如果存在,并且LoadBalancedRetryFactory不能存在时,则创建LoadBalancedRetryFactory对象
@Bean
@ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate")
@ConditionalOnMissingBean
public LoadBalancedRetryFactory loadBalancedRetryPolicyFactory(
final SpringClientFactory clientFactory) {
return new RibbonLoadBalancedRetryFactory(clientFactory);
}
// 当确实PropertiesFactory对象不存在时,则创建PropertiesFactory对象
@Bean
@ConditionalOnMissingBean
public PropertiesFactory propertiesFactory() {
return new PropertiesFactory();
}
// 当ribbon.eager-load.enabled的配置值为true时,创建RibbonApplicationContextInitializer对象
@Bean
@ConditionalOnProperty("ribbon.eager-load.enabled")
public RibbonApplicationContextInitializer ribbonApplicationContextInitializer() {
return new RibbonApplicationContextInitializer(springClientFactory(),
ribbonEagerLoadProperties.getClients());
}
// 该配置类型的装配,需要满足两个条件
// 1. classpath中包含了HttpRequest类
// 2. ribbon.restclient.enabled配置为true
@Configuration
@ConditionalOnClass(HttpRequest.class)
@ConditionalOnRibbonRestClient
protected static class RibbonClientHttpRequestFactoryConfiguration {
@Autowired
private SpringClientFactory springClientFactory;
// 创建RestTemplateCustomizer对象
@Bean
public RestTemplateCustomizer restTemplateCustomizer(
final RibbonClientHttpRequestFactory ribbonClientHttpRequestFactory) {
return restTemplate -> restTemplate
.setRequestFactory(ribbonClientHttpRequestFactory);
}
// 创建RibbonClientHttpRequestFactory对象
@Bean
public RibbonClientHttpRequestFactory ribbonClientHttpRequestFactory() {
return new RibbonClientHttpRequestFactory(this.springClientFactory);
}
}
@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 {
}
}
}
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); } // 创建SpringClientFactory对象 @Bean public SpringClientFactory springClientFactory() { SpringClientFactory factory = new SpringClientFactory(); factory.setConfigurations(this.configurations); return factory; } // 当LoadBalancerClient对象不存在时,创建LoadBalancerClient对象 @Bean @ConditionalOnMissingBean(LoadBalancerClient.class) public LoadBalancerClient loadBalancerClient() { return new RibbonLoadBalancerClient(springClientFactory()); } // 判断classpath中是否包含了RetryTemplate类,如果存在,并且LoadBalancedRetryFactory不能存在时,则创建LoadBalancedRetryFactory对象 @Bean @ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate") @ConditionalOnMissingBean public LoadBalancedRetryFactory loadBalancedRetryPolicyFactory( final SpringClientFactory clientFactory) { return new RibbonLoadBalancedRetryFactory(clientFactory); } // 当确实PropertiesFactory对象不存在时,则创建PropertiesFactory对象 @Bean @ConditionalOnMissingBean public PropertiesFactory propertiesFactory() { return new PropertiesFactory(); } // 当ribbon.eager-load.enabled的配置值为true时,创建RibbonApplicationContextInitializer对象 @Bean @ConditionalOnProperty("ribbon.eager-load.enabled") public RibbonApplicationContextInitializer ribbonApplicationContextInitializer() { return new RibbonApplicationContextInitializer(springClientFactory(), ribbonEagerLoadProperties.getClients()); } // 该配置类型的装配,需要满足两个条件 // 1. classpath中包含了HttpRequest类 // 2. ribbon.restclient.enabled配置为true @Configuration @ConditionalOnClass(HttpRequest.class) @ConditionalOnRibbonRestClient protected static class RibbonClientHttpRequestFactoryConfiguration { @Autowired private SpringClientFactory springClientFactory; // 创建RestTemplateCustomizer对象 @Bean public RestTemplateCustomizer restTemplateCustomizer( final RibbonClientHttpRequestFactory ribbonClientHttpRequestFactory) { return restTemplate -> restTemplate .setRequestFactory(ribbonClientHttpRequestFactory); } // 创建RibbonClientHttpRequestFactory对象 @Bean public RibbonClientHttpRequestFactory ribbonClientHttpRequestFactory() { return new RibbonClientHttpRequestFactory(this.springClientFactory); } } @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 { } } }
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);
    }

    // 创建SpringClientFactory对象
    @Bean
    public SpringClientFactory springClientFactory() {
        SpringClientFactory factory = new SpringClientFactory();
        factory.setConfigurations(this.configurations);
        return factory;
    }

    // 当LoadBalancerClient对象不存在时,创建LoadBalancerClient对象
    @Bean
    @ConditionalOnMissingBean(LoadBalancerClient.class)
    public LoadBalancerClient loadBalancerClient() {
        return new RibbonLoadBalancerClient(springClientFactory());
    }

    // 判断classpath中是否包含了RetryTemplate类,如果存在,并且LoadBalancedRetryFactory不能存在时,则创建LoadBalancedRetryFactory对象
    @Bean
    @ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate")
    @ConditionalOnMissingBean
    public LoadBalancedRetryFactory loadBalancedRetryPolicyFactory(
            final SpringClientFactory clientFactory) {
        return new RibbonLoadBalancedRetryFactory(clientFactory);
    }

    // 当确实PropertiesFactory对象不存在时,则创建PropertiesFactory对象
    @Bean
    @ConditionalOnMissingBean
    public PropertiesFactory propertiesFactory() {
        return new PropertiesFactory();
    }

    // 当ribbon.eager-load.enabled的配置值为true时,创建RibbonApplicationContextInitializer对象
    @Bean
    @ConditionalOnProperty("ribbon.eager-load.enabled")
    public RibbonApplicationContextInitializer ribbonApplicationContextInitializer() {
        return new RibbonApplicationContextInitializer(springClientFactory(),
                ribbonEagerLoadProperties.getClients());
    }

    // 该配置类型的装配,需要满足两个条件
    // 1. classpath中包含了HttpRequest类
    // 2. ribbon.restclient.enabled配置为true
    @Configuration
    @ConditionalOnClass(HttpRequest.class)
    @ConditionalOnRibbonRestClient
    protected static class RibbonClientHttpRequestFactoryConfiguration {

        @Autowired
        private SpringClientFactory springClientFactory;

        // 创建RestTemplateCustomizer对象
        @Bean
        public RestTemplateCustomizer restTemplateCustomizer(
                final RibbonClientHttpRequestFactory ribbonClientHttpRequestFactory) {
            return restTemplate -> restTemplate
                    .setRequestFactory(ribbonClientHttpRequestFactory);
        }

        // 创建RibbonClientHttpRequestFactory对象
        @Bean
        public RibbonClientHttpRequestFactory ribbonClientHttpRequestFactory() {
            return new RibbonClientHttpRequestFactory(this.springClientFactory);
        }

    }

    @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 {

        }

    }

}

LoadBalancerAutoConfiguration

该类加载是在RibbonAutoConfiguration装配完成后执行,该类的装在也是有条件的,所以我们可以具体看下。

条件判断

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Configuration
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)
@Configuration @ConditionalOnClass(RestTemplate.class) @ConditionalOnBean(LoadBalancerClient.class) @EnableConfigurationProperties(LoadBalancerRetryProperties.class)
@Configuration
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)

通过注解头的条件声明,可以看到,该类的装配需要满足一下条件:

  • 在classpath中包含了RestTemplate类
  • 在spring容器中包含了LoadBalancerClient对象
  • 自动加载LoadBalancerRetryProperites配置

装载中

在该配置类型的装在过程中,最主要的部分则是生成LoadBalancerRequestFactorySmartInitialzingSingleton的bean实例。同事判断是否包含了RetryTemplate, 一次做增量的装配。具体源码如下

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@LoadBalanced
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();
@Autowired(required = false)
private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();
// 创建SmartInitializingSingleton bean实例
@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);
}
}
});
}
// 创建LoadBalancerRequestFactory 实例
@Bean
@ConditionalOnMissingBean
public LoadBalancerRequestFactory loadBalancerRequestFactory(
LoadBalancerClient loadBalancerClient) {
return new LoadBalancerRequestFactory(loadBalancerClient, this.transformers);
}
@LoadBalanced @Autowired(required = false) private List<RestTemplate> restTemplates = Collections.emptyList(); @Autowired(required = false) private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList(); // 创建SmartInitializingSingleton bean实例 @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); } } }); } // 创建LoadBalancerRequestFactory 实例 @Bean @ConditionalOnMissingBean public LoadBalancerRequestFactory loadBalancerRequestFactory( LoadBalancerClient loadBalancerClient) { return new LoadBalancerRequestFactory(loadBalancerClient, this.transformers); }
@LoadBalanced
    @Autowired(required = false)
    private List<RestTemplate> restTemplates = Collections.emptyList();

    @Autowired(required = false)
    private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();

    // 创建SmartInitializingSingleton bean实例
    @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);
                }
            }
        });
    }

    // 创建LoadBalancerRequestFactory 实例
    @Bean
    @ConditionalOnMissingBean
    public LoadBalancerRequestFactory loadBalancerRequestFactory(
            LoadBalancerClient loadBalancerClient) {
        return new LoadBalancerRequestFactory(loadBalancerClient, this.transformers);
    }

同时会根据在classpath中依赖包的变化,动态扩展加载,具体源码如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// 判断在classpath中是否包含了RetryTemplate类, 如果不包含,则装配LoadBalancerInterceptorConfig
@Configuration
@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
static class LoadBalancerInterceptorConfig {
// 创建LoadBalancerInterceptor
@Bean
public LoadBalancerInterceptor ribbonInterceptor(
LoadBalancerClient loadBalancerClient,
LoadBalancerRequestFactory requestFactory) {
return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
}
// 创建RestTemplateCustomizer
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(
final LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(
restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
};
}
}
/**
* Auto configuration for retry mechanism.
*/
@Configuration
@ConditionalOnClass(RetryTemplate.class)
public static class RetryAutoConfiguration {
// 创建LoadBalancedRetryFactory对象
@Bean
@ConditionalOnMissingBean
public LoadBalancedRetryFactory loadBalancedRetryFactory() {
return new LoadBalancedRetryFactory() {
};
}
}
/**
* Auto configuration for retry intercepting mechanism.
*/
@Configuration
@ConditionalOnClass(RetryTemplate.class)
public static class RetryInterceptorAutoConfiguration {
// 创建RetryLoadBalancerInterceptor对象
@Bean
@ConditionalOnMissingBean
public RetryLoadBalancerInterceptor ribbonInterceptor(
LoadBalancerClient loadBalancerClient,
LoadBalancerRetryProperties properties,
LoadBalancerRequestFactory requestFactory,
LoadBalancedRetryFactory loadBalancedRetryFactory) {
return new RetryLoadBalancerInterceptor(loadBalancerClient, properties,
requestFactory, loadBalancedRetryFactory);
}
// 创建RestTemplateCustomizer对象
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(
final RetryLoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(
restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
};
}
}
// 判断在classpath中是否包含了RetryTemplate类, 如果不包含,则装配LoadBalancerInterceptorConfig @Configuration @ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate") static class LoadBalancerInterceptorConfig { // 创建LoadBalancerInterceptor @Bean public LoadBalancerInterceptor ribbonInterceptor( LoadBalancerClient loadBalancerClient, LoadBalancerRequestFactory requestFactory) { return new LoadBalancerInterceptor(loadBalancerClient, requestFactory); } // 创建RestTemplateCustomizer @Bean @ConditionalOnMissingBean public RestTemplateCustomizer restTemplateCustomizer( final LoadBalancerInterceptor loadBalancerInterceptor) { return restTemplate -> { List<ClientHttpRequestInterceptor> list = new ArrayList<>( restTemplate.getInterceptors()); list.add(loadBalancerInterceptor); restTemplate.setInterceptors(list); }; } } /** * Auto configuration for retry mechanism. */ @Configuration @ConditionalOnClass(RetryTemplate.class) public static class RetryAutoConfiguration { // 创建LoadBalancedRetryFactory对象 @Bean @ConditionalOnMissingBean public LoadBalancedRetryFactory loadBalancedRetryFactory() { return new LoadBalancedRetryFactory() { }; } } /** * Auto configuration for retry intercepting mechanism. */ @Configuration @ConditionalOnClass(RetryTemplate.class) public static class RetryInterceptorAutoConfiguration { // 创建RetryLoadBalancerInterceptor对象 @Bean @ConditionalOnMissingBean public RetryLoadBalancerInterceptor ribbonInterceptor( LoadBalancerClient loadBalancerClient, LoadBalancerRetryProperties properties, LoadBalancerRequestFactory requestFactory, LoadBalancedRetryFactory loadBalancedRetryFactory) { return new RetryLoadBalancerInterceptor(loadBalancerClient, properties, requestFactory, loadBalancedRetryFactory); } // 创建RestTemplateCustomizer对象 @Bean @ConditionalOnMissingBean public RestTemplateCustomizer restTemplateCustomizer( final RetryLoadBalancerInterceptor loadBalancerInterceptor) { return restTemplate -> { List<ClientHttpRequestInterceptor> list = new ArrayList<>( restTemplate.getInterceptors()); list.add(loadBalancerInterceptor); restTemplate.setInterceptors(list); }; } }
    // 判断在classpath中是否包含了RetryTemplate类, 如果不包含,则装配LoadBalancerInterceptorConfig 
    @Configuration
    @ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
    static class LoadBalancerInterceptorConfig {

        // 创建LoadBalancerInterceptor
        @Bean
        public LoadBalancerInterceptor ribbonInterceptor(
                LoadBalancerClient loadBalancerClient,
                LoadBalancerRequestFactory requestFactory) {
            return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
        }

        // 创建RestTemplateCustomizer
        @Bean
        @ConditionalOnMissingBean
        public RestTemplateCustomizer restTemplateCustomizer(
                final LoadBalancerInterceptor loadBalancerInterceptor) {
            return restTemplate -> {
                List<ClientHttpRequestInterceptor> list = new ArrayList<>(
                        restTemplate.getInterceptors());
                list.add(loadBalancerInterceptor);
                restTemplate.setInterceptors(list);
            };
        }

    }

    /**
     * Auto configuration for retry mechanism.
     */
    @Configuration
    @ConditionalOnClass(RetryTemplate.class)
    public static class RetryAutoConfiguration {

        // 创建LoadBalancedRetryFactory对象
        @Bean
        @ConditionalOnMissingBean
        public LoadBalancedRetryFactory loadBalancedRetryFactory() {
            return new LoadBalancedRetryFactory() {
            };
        }

    }

    /**
     * Auto configuration for retry intercepting mechanism.
     */
    @Configuration
    @ConditionalOnClass(RetryTemplate.class)
    public static class RetryInterceptorAutoConfiguration {

        // 创建RetryLoadBalancerInterceptor对象
        @Bean
        @ConditionalOnMissingBean
        public RetryLoadBalancerInterceptor ribbonInterceptor(
                LoadBalancerClient loadBalancerClient,
                LoadBalancerRetryProperties properties,
                LoadBalancerRequestFactory requestFactory,
                LoadBalancedRetryFactory loadBalancedRetryFactory) {
            return new RetryLoadBalancerInterceptor(loadBalancerClient, properties,
                    requestFactory, loadBalancedRetryFactory);
        }

        // 创建RestTemplateCustomizer对象
        @Bean
        @ConditionalOnMissingBean
        public RestTemplateCustomizer restTemplateCustomizer(
                final RetryLoadBalancerInterceptor loadBalancerInterceptor) {
            return restTemplate -> {
                List<ClientHttpRequestInterceptor> list = new ArrayList<>(
                        restTemplate.getInterceptors());
                list.add(loadBalancerInterceptor);
                restTemplate.setInterceptors(list);
            };
        }

    }

AsyncLoadBalancerAutoConfiguration

该装配类型也是后置装配中的一个重要的类, 该类同样也需要满足条件后才能开始装配。

条件判断

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Configuration
@ConditionalOnBean(LoadBalancerClient.class)
@ConditionalOnClass(AsyncRestTemplate.class)
@Configuration @ConditionalOnBean(LoadBalancerClient.class) @ConditionalOnClass(AsyncRestTemplate.class)
@Configuration
@ConditionalOnBean(LoadBalancerClient.class)
@ConditionalOnClass(AsyncRestTemplate.class)

该类的装配条件需要满足两个方面:

  • 在classpath中包含了SyncRestTemplate类
  • 在spring容器中包含了LoadBalancerClient对象

装配中

装配中包含了两个内部的配置类型,具体源码如下;

AsyncRestTemplateCustomizerConfig

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Configuration
static class AsyncRestTemplateCustomizerConfig {
// 注入所有的AsyncRestTemplate bean
@LoadBalanced
@Autowired(required = false)
private List<AsyncRestTemplate> restTemplates = Collections.emptyList();
// 创建SmartInitializingSingleton对象
@Bean
public SmartInitializingSingleton loadBalancedAsyncRestTemplateInitializer(
final List<AsyncRestTemplateCustomizer> customizers) {
return new SmartInitializingSingleton() {
@Override
public void afterSingletonsInstantiated() {
for (AsyncRestTemplate restTemplate : AsyncRestTemplateCustomizerConfig.this.restTemplates) {
for (AsyncRestTemplateCustomizer customizer : customizers) {
customizer.customize(restTemplate);
}
}
}
};
}
}
@Configuration static class AsyncRestTemplateCustomizerConfig { // 注入所有的AsyncRestTemplate bean @LoadBalanced @Autowired(required = false) private List<AsyncRestTemplate> restTemplates = Collections.emptyList(); // 创建SmartInitializingSingleton对象 @Bean public SmartInitializingSingleton loadBalancedAsyncRestTemplateInitializer( final List<AsyncRestTemplateCustomizer> customizers) { return new SmartInitializingSingleton() { @Override public void afterSingletonsInstantiated() { for (AsyncRestTemplate restTemplate : AsyncRestTemplateCustomizerConfig.this.restTemplates) { for (AsyncRestTemplateCustomizer customizer : customizers) { customizer.customize(restTemplate); } } } }; } }
@Configuration
    static class AsyncRestTemplateCustomizerConfig {

        // 注入所有的AsyncRestTemplate bean
        @LoadBalanced
        @Autowired(required = false)
        private List<AsyncRestTemplate> restTemplates = Collections.emptyList();

        // 创建SmartInitializingSingleton对象
        @Bean
        public SmartInitializingSingleton loadBalancedAsyncRestTemplateInitializer(
                final List<AsyncRestTemplateCustomizer> customizers) {
            return new SmartInitializingSingleton() {
                @Override
                public void afterSingletonsInstantiated() {
                    for (AsyncRestTemplate restTemplate : AsyncRestTemplateCustomizerConfig.this.restTemplates) {
                        for (AsyncRestTemplateCustomizer customizer : customizers) {
                            customizer.customize(restTemplate);
                        }
                    }
                }
            };
        }

    }

LoadBalancerInterceptorConfig

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Configuration
static class LoadBalancerInterceptorConfig {
// 创建AsyncLoadBalancerInterceptor bean
@Bean
public AsyncLoadBalancerInterceptor asyncLoadBalancerInterceptor(
LoadBalancerClient loadBalancerClient) {
return new AsyncLoadBalancerInterceptor(loadBalancerClient);
}
// AsyncRestTemplateCustomizer bean
@Bean
public AsyncRestTemplateCustomizer asyncRestTemplateCustomizer(
final AsyncLoadBalancerInterceptor loadBalancerInterceptor) {
return new AsyncRestTemplateCustomizer() {
@Override
public void customize(AsyncRestTemplate restTemplate) {
List<AsyncClientHttpRequestInterceptor> list = new ArrayList<>(
restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
}
};
}
@Configuration static class LoadBalancerInterceptorConfig { // 创建AsyncLoadBalancerInterceptor bean @Bean public AsyncLoadBalancerInterceptor asyncLoadBalancerInterceptor( LoadBalancerClient loadBalancerClient) { return new AsyncLoadBalancerInterceptor(loadBalancerClient); } // AsyncRestTemplateCustomizer bean @Bean public AsyncRestTemplateCustomizer asyncRestTemplateCustomizer( final AsyncLoadBalancerInterceptor loadBalancerInterceptor) { return new AsyncRestTemplateCustomizer() { @Override public void customize(AsyncRestTemplate restTemplate) { List<AsyncClientHttpRequestInterceptor> list = new ArrayList<>( restTemplate.getInterceptors()); list.add(loadBalancerInterceptor); restTemplate.setInterceptors(list); } }; }
@Configuration
    static class LoadBalancerInterceptorConfig {

                // 创建AsyncLoadBalancerInterceptor bean
        @Bean
        public AsyncLoadBalancerInterceptor asyncLoadBalancerInterceptor(
                LoadBalancerClient loadBalancerClient) {
            return new AsyncLoadBalancerInterceptor(loadBalancerClient);
        }

                // AsyncRestTemplateCustomizer bean
        @Bean
        public AsyncRestTemplateCustomizer asyncRestTemplateCustomizer(
                final AsyncLoadBalancerInterceptor loadBalancerInterceptor) {
            return new AsyncRestTemplateCustomizer() {
                @Override
                public void customize(AsyncRestTemplate restTemplate) {
                    List<AsyncClientHttpRequestInterceptor> list = new ArrayList<>(
                            restTemplate.getInterceptors());
                    list.add(loadBalancerInterceptor);
                    restTemplate.setInterceptors(list);
                }
            };
        }

 

以上就是spring cloud ribbon自动装配的过程。该篇文章只是介绍在自动装配中的过程,不涉及具体的业务逻辑,后续章节将介绍在ribbon中每个类的作用,以及具体的代码实现细节。

 

Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注