SpringCloud升级之路2020.0.x版-9.如何理解并定制一个Spring Cloud组件

简介: SpringCloud升级之路2020.0.x版-9.如何理解并定制一个Spring Cloud组件

本系列为之前系列的整理重启版,随着项目的发展以及项目中的使用,之前系列里面很多东西发生了变化,并且还有一些东西之前系列并没有提到,所以重启这个系列重新整理下,欢迎各位留言交流,谢谢!~

我们实现的 Spring Cloud 微服务框架,里面运用了许多 Spring Cloud 组件,并且对于某些组件进行了个性化改造。那么对于某个 Spring Cloud 组件,我们一般是如何入手理解其中的原理呢?以及如何知道其中的扩展点呢?一般从下面两个方面入手:

  1. 通过 spring-boot SPI 机制查看模块的扩展点
  2. 查看该模块实现的 NamedContextFactory


image.png


spring-core 项目中提供了 Spring 框架多种 SPI 机制,其中一种非常常用并灵活运用在了 Spring-boot 的机制就是基于 spring.factories 的 SPI 机制。

那么什么是 SPI(Service Provider)呢? 在系统设计中,为了模块间的协作,往往会设计统一的接口供模块之间的调用。面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码,而是将指定哪个实现置于程序之外指定。Java 中默认的 SPI 机制就是通过 ServiceLoader 来实现,简单来说就是通过在META-INF/services目录下新建一个名称为接口全限定名的文件,内容为接口实现类的全限定名,之后程序通过代码:

//指定加载的接口类,以及用来加载类的类加载器,如果类加载器为 null 则用根类加载器加载
ServiceLoader<SpiService> serviceLoader = ServiceLoader.load(SpiService.class, someClassLoader);
Iterator<SpiService> iterator = serviceLoader.iterator();
while (iterator.hasNext()){
    SpiService spiService = iterator.next();
}

获取指定的实现类。

在 Spring 框架中,这个类是SpringFactoriesLoader,需要在META-INF/spring.factories文件中指定接口以及对应的实现类,例如 Spring Cloud Commons 中的:

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.cloud.client.HostInfoEnvironmentPostProcessor

其中指定了EnvironmentPostProcessor的实现HostInfoEnvironmentPostProcessor

同时,Spring Boot 中会通过SpringFactoriesLoader.loadXXX类似的方法读取所有的EnvironmentPostProcessor的实现类并生成 Bean 到 ApplicationContext 中:

EnvironmentPostProcessorApplicationListener

//这个类也是通过spring.factories中指定ApplicationListener的实现而实现加载的,这里省略
public class EnvironmentPostProcessorApplicationListener implements SmartApplicationListener, Ordered {
    //创建这个Bean的时候,会调用
    public EnvironmentPostProcessorApplicationListener() {
    this(EnvironmentPostProcessorsFactory
        .fromSpringFactories(EnvironmentPostProcessorApplicationListener.class.getClassLoader()));
  }
}

EnvironmentPostProcessorsFactory

static EnvironmentPostProcessorsFactory fromSpringFactories(ClassLoader classLoader) {
  return new ReflectionEnvironmentPostProcessorsFactory(
          //通过 SpringFactoriesLoader.loadFactoryNames 获取文件中指定的实现类并初始化
      SpringFactoriesLoader.loadFactoryNames(EnvironmentPostProcessor.class, classLoader));
}


image.png


META-INF/spring.factories 文件中不一定指定的是接口以及对应的实现类,例如:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration,\

其中EnableAutoConfiguration是一个注解,LoadBalancerAutoConfigurationBlockingLoadBalancerClientAutoConfiguration都是配置类并不是EnableAutoConfiguration的实现。那么这个是什么意思呢?EnableAutoConfiguration是一个注解,LoadBalancerAutoConfigurationBlockingLoadBalancerClientAutoConfiguration都是配置类。spring.factories这里是另一种特殊使用,记录要载入的 Bean 类。EnableAutoConfiguration在注解被使用的时候,这些 Bean 会被加载。这就是spring.factories的另外一种用法。

EnableAutoConfiguration是 Spring-boot 自动装载的核心注解。有了这个注解,Spring-boot 就可以自动加载各种@Configuration注解的类。那么这个机制是如何实现的呢?

来看下EnableAutoConfiguration的源码 EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
  String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
  //排除的类
  Class<?>[] exclude() default {};
  //排除的Bean名称
  String[] excludeName() default {};
}

我们看到了有 @Import 这个注解。这个注解是 Spring 框架的一个很常用的注解,是 Spring 基于 Java 注解配置的主要组成部分。


image.png


  1. 查看 jar 包的 META-INF/spring.factories
  2. 查看里面的内容,尤其关注 org.springframework.boot.autoconfigure.EnableAutoConfiguration= 自动加载的配置类
  3. 查看自动加载的配置类,关注哪些 Bean 可以扩展(例如,包含@ConditionalOnMissingBean 注解的 Bean)



image.png


我们一般想个性化定制都是针对调用不同微服务不同的 Bean 配置,所以其实要重点关注的就是这个模块扩展的 NamedContextFactory:

  1. 寻找这个组件扩展 NamedContextFactory 的类
  2. 查看类的源代码,查看默认配置是什么类,以及 Specification 是什么类,以及如何获取当前微服务的名称。
  3. 根据默认配置类,查看里面的 Bean 有哪些,并且哪些可以被替换(例如,包含@ConditionalOnMissingBean 注解的 Bean)
  4. 根据 Specification 查看扩展配置的方式

我们这里拿 spring-cloud-loadbalancer 举一个简单例子,即:

spring-cloud-loadbalancer 中扩展 NamedContextFactory 的类是 LoadBalancerClientFactory,查看 LoadBalancerClientFactory 的代码可以知道:


image.png


  1. 可以通过 loadbalancer.client.name 这个属性获取当前要创建的 Bean 是哪个微服务的
  2. 可以知道默认配置是 LoadBalancerClientConfiguration,再查看它里面的源代码我们可以知道主要初始化两个 Bean:
  1. ReactorLoadBalancer,负载均衡器,因为有 @ConditionalOnMissingBean 所以可以被替换,这就是我们的扩展点
  2. ServiceInstanceSupplier,提供实例信息的 Supplier,因为有 @ConditionalOnMissingBean 所以可以被替换,这就是我们的扩展点


  1. Specification 为 LoadBalancerSpecification,再分析其调用可以知道,可以通过 @LoadBalancerClient@LoadBalancerClientsLoadBalancerClientConfiguration 的基础上额外指定配置。


image.png


我们这一节详细分析了如何使用以及分析改造一个 Spring Cloud 组件。下一节我们将开始具体分析我们实现的微服务框架的每一块功能。

相关实践学习
部署高可用架构
本场景主要介绍如何使用云服务器ECS、负载均衡SLB、云数据库RDS和数据传输服务产品来部署多可用区高可用架构。
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
2天前
|
移动开发 前端开发 NoSQL
ruoyi-nbcio从spring2.7.18升级springboot到3.1.7,java从java8升级到17(二)
ruoyi-nbcio从spring2.7.18升级springboot到3.1.7,java从java8升级到17(二)
12 0
|
2天前
|
监控 安全 Java
Spring cloud原理详解
Spring cloud原理详解
14 0
|
7天前
|
消息中间件 负载均衡 Java
【Spring Cloud 初探幽】
【Spring Cloud 初探幽】
14 1
|
8天前
|
Java 开发者 微服务
Spring Cloud原理详解
【5月更文挑战第4天】Spring Cloud是Spring生态系统中的微服务框架,包含配置管理、服务发现、断路器、API网关等工具,简化分布式系统开发。核心组件如Eureka(服务发现)、Config Server(配置中心)、Ribbon(负载均衡)、Hystrix(断路器)、Zuul(API网关)等。本文讨论了Spring Cloud的基本概念、核心组件、常见问题及解决策略,并提供代码示例,帮助开发者更好地理解和实践微服务架构。此外,还涵盖了服务通信方式、安全性、性能优化、自动化部署、服务网格和无服务器架构的融合等话题,揭示了微服务架构的未来趋势。
32 6
|
13天前
|
JSON Java Apache
Spring Cloud Feign 使用Apache的HTTP Client替换Feign原生httpclient
Spring Cloud Feign 使用Apache的HTTP Client替换Feign原生httpclient
|
13天前
|
负载均衡 Java 开发者
Spring Cloud:一文读懂其原理与架构
Spring Cloud 是一套微服务解决方案,它整合了Netflix公司的多个开源框架,简化了分布式系统开发。Spring Cloud 提供了服务注册与发现、配置中心、消息总线、负载均衡、熔断机制等工具,让开发者可以快速地构建一些常见的微服务架构。
|
15天前
|
消息中间件 Java RocketMQ
Spring Cloud RocketMQ:构建可靠消息驱动的微服务架构
【4月更文挑战第28天】消息队列在微服务架构中扮演着至关重要的角色,能够实现服务之间的解耦、异步通信以及数据分发。Spring Cloud RocketMQ作为Apache RocketMQ的Spring Cloud集成,为微服务架构提供了可靠的消息传输机制。
28 1
|
15天前
|
Dubbo Java 应用服务中间件
Spring Cloud Dubbo: 微服务通信的高效解决方案
【4月更文挑战第28天】在微服务架构的发展中,服务间的高效通信至关重要。Spring Cloud Dubbo 提供了一种基于 RPC 的通信方式,使得服务间的调用就像本地方法调用一样简单。本篇博客将探讨 Spring Cloud Dubbo 的核心概念,并通过具体实例展示其在项目中的实战应用。
15 2
|
15天前
|
监控 Java Sentinel
Spring Cloud Sentinel:概念与实战应用
【4月更文挑战第28天】在分布式微服务架构中,确保系统的稳定性和可靠性至关重要。Spring Cloud Sentinel 为微服务提供流量控制、熔断降级和系统负载保护,有效预防服务雪崩。本篇博客深入探讨 Spring Cloud Sentinel 的核心概念,并通过实际案例展示其在项目中的应用。
24 0