2

Spring 源码解析十五:SpringCloud 的基础组件

SpringCloud 并不是只有一个项目,而是很多项目构成的生态体系总称,如

但这些项目都依赖一个基础项目 spring-cloud-commons

spring-cloud-commons 主要有 3 个模块

  • spring-cloud-context:构建一个 Bootstrap 容器,并让其成为原有的 SpringBoot 程序构建的容器的父容器,所以使用 SpringCloud 的方式与 SpringBoot 是差不多的
  • spring-cloud-commons:对微服务中的服务注册与发现、负载均衡、熔断器等功能提供一个抽象层代码,这个抽象层与具体的实现无关,这些功能可以采用不同的技术去实现
  • spring-cloud-loadbalancer:一个客户端负载均衡器,类似于 Ribbon,用于替换 Ribbon(Ribbon 已经进入维护模式)

1. spring-cloud-context

组件的加载仍然是通过 Spring Factories 扩展加载机制加载的,定在 spring.factories

# 属性自动装配
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.cloud.autoconfigure.LifecycleMvcEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.WritableEnvironmentEndpointAutoConfiguration

# 应用监听器
org.springframework.context.ApplicationListener=\
org.springframework.cloud.bootstrap.BootstrapApplicationListener,\
org.springframework.cloud.bootstrap.LoggingSystemShutdownListener,\
org.springframework.cloud.context.restart.RestartListener

# Spring Cloud 初始化组件
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration,\
org.springframework.cloud.bootstrap.encrypt.EncryptionBootstrapConfiguration,\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration

# Spring Boot 初始化注册
org.springframework.boot.BootstrapRegistryInitializer=\
org.springframework.cloud.bootstrap.RefreshBootstrapRegistryInitializer,\
org.springframework.cloud.bootstrap.TextEncryptorConfigBootstrapper

# 环境后置处理
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.cloud.bootstrap.encrypt.DecryptEnvironmentPostProcessor,\
org.springframework.cloud.util.random.CachedRandomPropertySourceEnvironmentPostProcessor

下面主要解析一下 BootstrapApplicationListenerPropertySourceBootstrapConfiguration

1.1. BootstrapApplicationListener

BootstrapApplicationListener
的主要功能是扩展配置文件的加载位置、添加 spring.factories 的加载组件

public class BootstrapApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
    @Override
    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
        // ... 代码省略

        // 初始化上下文环境
        context = bootstrapServiceContext(environment, event.getSpringApplication(), configName);

        // ... 代码省略
    }

    // 初始化上下文环境
    private ConfigurableApplicationContext bootstrapServiceContext(ConfigurableEnvironment environment,
                final SpringApplication application, String configName) {
        // ... 代码省略

        String configLocation = environment.resolvePlaceholders("${spring.cloud.bootstrap.location:}");
        String configAdditionalLocation = environment
                .resolvePlaceholders("${spring.cloud.bootstrap.additional-location:}");
        Map<String, Object> bootstrapMap = new HashMap<>();

        // 扩展 spring.cloud.bootstrap.location 配置到 spring.config.location 中
        if (StringUtils.hasText(configLocation)) {
            bootstrapMap.put("spring.config.location", configLocation);
        }
        // 扩展 spring.cloud.bootstrap.additional-location 配置到 spring.config.additional-location 中
        if (StringUtils.hasText(configAdditionalLocation)) {
            bootstrapMap.put("spring.config.additional-location", configAdditionalLocation);
        }

        // ... 代码省略

        // 通过 BootstrapImportSelector 添加 `spring.factories` 的加载组件 `org.springframework.cloud.bootstrap.BootstrapConfiguration`
        builder.sources(BootstrapImportSelectorConfiguration.class);
    }
}
public class BootstrapImportSelector implements EnvironmentAware, DeferredImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        // ... 代码省略

        // 通过 SpringFactoriesLoader 加载 `org.springframework.cloud.bootstrap.BootstrapConfiguration` 指定的组件
        List<String> names = new ArrayList<>(
                SpringFactoriesLoader.loadFactoryNames(BootstrapConfiguration.class, classLoader));
        // 配置中的 spring.cloud.bootstrap.sources 也当做 BootstrapConfiguration 组件加载
        names.addAll(Arrays.asList(StringUtils
                .commaDelimitedListToStringArray(this.environment.getProperty("spring.cloud.bootstrap.sources", ""))));

        // ... 代码省略
    }
}

1.2. PropertySourceBootstrapConfiguration

PropertySourceBootstrapConfiguration
的主要功能是针对 SpringCloud 的日志、Profile、配置处理

public class PropertySourceBootstrapConfiguration
        implements ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        // ... 代码省略

        MutablePropertySources propertySources = environment.getPropertySources();

        // ... 代码省略

        // 加载自定义的配置加载处理,spring-cloud-config 的分布式配置功能就有赖于此
        insertPropertySources(propertySources, composite);

        // 处理 logging.config 指定的日志配置
        String logConfig = environment.resolvePlaceholders("${logging.config:}");
        LogFile logFile = LogFile.get(environment);
        reinitializeLoggingSystem(environment, logConfig, logFile);

        // 设置日志记录等级
        setLogLevels(applicationContext, environment);

        // 处理 spring.profiles.active 激活的环境
        handleIncludedProfiles(environment);
    }
}

1.3. @BootstrapConfiguration

这个注解是 spring-cloud-context 主要的注解,用于初始化 Spring Cloud 组件

BootstrapConfiguration

// 通过前面介绍的 `BootstrapImportSelector` 来实现自动加载在 `spring.factories` 中使用
// `org.springframework.cloud.bootstrap.BootstrapConfiguration` 配置的类
public @interface BootstrapConfiguration {}

2. spring-cloud-commons

组件的加载仍然是通过 Spring Factories 扩展加载机制加载的,定在 spring.factories

# 属性自动装配
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.client.CommonsClientAutoConfiguration,\
org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration,\
org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration,\
org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration,\
org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration,\
org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryClientAutoConfiguration,\
org.springframework.cloud.client.hypermedia.CloudHypermediaAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,\
org.springframework.cloud.commons.httpclient.HttpClientConfiguration,\
org.springframework.cloud.commons.util.UtilAutoConfiguration,\
org.springframework.cloud.configuration.CompatibilityVerifierAutoConfiguration,\
org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration,\
org.springframework.cloud.commons.security.ResourceServerTokenRelayAutoConfiguration

# 环境后置处理
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.cloud.client.HostInfoEnvironmentPostProcessor

# 错误分析
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.cloud.configuration.CompatibilityNotMetFailureAnalyzer

2.1. @EnableDiscoveryClient & @LoadBalanced

这两个注解是 spring-cloud-commons 主要的注解,@EnableDiscoveryClient 用于添加服务发现客户端,@LoadBalanced 用于标志请求是负载均衡的

EnableDiscoveryClient

// 自动实例化 `EnableDiscoveryClientImportSelector`,并载入Spring IOC容器
// 实例化 `@EnableDiscoveryClient` 注解的类,但不做实际注册、发现处理
@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {}

LoadBalanced

// 没有任何处理,只是定义注解
public @interface LoadBalanced {}

@EnableDiscoveryClient@LoadBalanced 都没有实质上的处理,只是定义好注解规范,留待其他组件实现

3. spring-cloud-loadbalancer

组件的加载仍然是通过 Spring Factories 扩展加载机制加载的,定在 spring.factories

# 属性自动装配
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerCacheAutoConfiguration,\
org.springframework.cloud.loadbalancer.security.OAuth2LoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerStatsAutoConfiguration

这里主要解析一下 LoadBalancerAutoConfiguration

3.1. LoadBalancerAutoConfiguration

LoadBalancerAutoConfiguration
的主要功能是完成 spring.cloud.loadbalancer 的自动配置装配,并实例化负载均衡组件

// 继承 `LoadBalancerClients` 的注解
@LoadBalancerClients
// 自动装配 `spring.cloud.loadbalancer` 配置
@EnableConfigurationProperties(LoadBalancerProperties.class)
// 使用 `spring.cloud.loadbalancer.enabled` 来启动此组件
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.enabled", havingValue = "true", matchIfMissing = true)
public class LoadBalancerAutoConfiguration {
    // ... 代码省略
}

因为 LoadBalancerAutoConfiguration 继承了 LoadBalancerClients
的注解,所以来看看 LoadBalancerClients

// 自动实例化 `LoadBalancerClientConfigurationRegistrar`,并载入Spring IOC容器
@Import(LoadBalancerClientConfigurationRegistrar.class)
public @interface LoadBalancerClients {
    // ... 代码省略
}

再来看看 LoadBalancerClientConfigurationRegistrar

public class LoadBalancerClientConfigurationRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        // 获取 @LoadBalancerClients 注解
        Map<String, Object> attrs = metadata.getAnnotationAttributes(LoadBalancerClients.class.getName(), true);
        if (attrs != null && attrs.containsKey("value")) {
            // 获取注解中 value 指定的值,并注册bean组件定义
            AnnotationAttributes[] clients = (AnnotationAttributes[]) attrs.get("value");
            for (AnnotationAttributes client : clients) {
                registerClientConfiguration(registry, getClientName(client), client.get("configuration"));
            }
        }

        // ... 代码省略

        // 获取 @LoadBalancerClient 注解
        Map<String, Object> client = metadata.getAnnotationAttributes(LoadBalancerClient.class.getName(), true);
        // 获取注解中 name/value 指定的值,并注册bean组件定义
        String name = getClientName(client);
        if (name != null) {
            registerClientConfiguration(registry, name, client.get("configuration"));
        }
    }
}

3.2. @LoadBalancerClients & @LoadBalancerClient

这两个注解是 spring-cloud-loadbalancer 主要的注解,用于添加负载均衡客户端

LoadBalancerClients

// 自动实例化 `LoadBalancerClientConfigurationRegistrar`,并载入Spring IOC容器
// 自动处理标记有 `@LoadBalancerClients` & `@LoadBalancerClient` 注解的类
@Import(LoadBalancerClientConfigurationRegistrar.class)
public @interface LoadBalancerClients {
    // ... 代码省略
}

LoadBalancerClient

// 自动实例化 `LoadBalancerClientConfigurationRegistrar`,并载入Spring IOC容器
// 自动处理标记有 `@LoadBalancerClients` & `@LoadBalancerClient` 注解的类
@Import(LoadBalancerClientConfigurationRegistrar.class)
public @interface LoadBalancerClient {
    // ... 代码省略
}

后续

更多博客,查看 https://github.com/senntyou/blogs

作者:深予之 (@senntyou)

版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证


深雨
12.7k 声望6.5k 粉丝

达则兼济天下,穷则独善其身。