zoukankan      html  css  js  c++  java
  • Spring Cloud Config

    前置知识:事件机制 应用上下文

    Bootstrap 应用上下文

    Bootstrap 上下文是 Spring Cloud 新引入的,与传统 Spring 上下文相同,即 ConfigurableApplicationContext 实例,由 BootstrapApplicationListener 监听 ApplicationEnvironmentPreparedEvent 事件时创建。

    而由于 ConfigurableApplicationContext 继承 ApplicationContext,有了层次关系,或者说父子关系。

    public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
        // ...
    }
    

    通过 setParent(@Nullable ApplicationContext parent) 可以设置上下文的层级关系。

    我们可以在 pom 文件中引入 Spring Boot 和 Spring Cloud 的依赖,启用 actuator

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    

    application.properties 中开启 Actuator Web 访问端口

    management.server.port=8081
    management.endpoints.jmx.exposure.include=*
    management.endpoints.web.exposure.include=*
    management.endpoint.health.show-details=always
    
    

    访问 http://127.0.0.1:8081/actuator/beans 可以看到 Spring Cloud Config 的上下文 是父,而 Spring Boot 的上下文是子。

    我们也可以自定义我们自己的应用上下文,

    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    @RestController
    public class DemoApplication {
    
        public static void main(String[] args) {
    
    	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    	context.setId("心灵蚂蚁");
    	context.registerBean("helloWorld", String.class, "hello,world"); // 注册bean给子类上下文使用
    	context.refresh();
    	new SpringApplicationBuilder(DemoApplication.class)
    			.parent(context)
    			.run(args);
    //	SpringApplication.run(DemoApplication.class, args);
        }
    }
    

    为什么 Spring Cloud 上下文要比 Spring Boot 的上下文加载的早以及 BootstrapApplicationListener 是何时加载进来的

    可以查看 事件机制

    Spring Cloud Server

    启动代码

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    @SpringBootApplication
    @EnableDiscoveryClient
    public class ConsumerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApplication.class, args);
        }
    
    }
    
    分析 @EnableConfigServer
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(ConfigServerConfiguration.class)
    public @interface EnableConfigServer {
    
    }
    

    实际配置类 ConfigServerConfiguration

    @Configuration
    public class ConfigServerConfiguration {
        class Marker {}
    
        @Bean
        public Marker enableConfigServerMarker() {
    	return new Marker();
        }
    }
    

    查看 使用 Marker 的地方,我们可以看到在 ConfigServerAutoConfiguration

    @Configuration
    @ConditionalOnBean(ConfigServerConfiguration.Marker.class)
    @EnableConfigurationProperties(ConfigServerProperties.class)
    @Import({ EnvironmentRepositoryConfiguration.class, CompositeConfiguration.class, ResourceRepositoryConfiguration.class,
    		ConfigServerEncryptionConfiguration.class, ConfigServerMvcConfiguration.class })
    public class ConfigServerAutoConfiguration {
    
    }
    

    也就是通过注解 @EnableConfigServer 创建实例 Maker() 作为一个“开关”,然后在自动配置类 ConfigServerAutoConfiguration 中执行真正的代码逻辑。

    Server 端支持什么方式获取配置信息

    在类 EnvironmentRepositoryConfiguration 中,我们可以看到除了默认的 Git,还有 JDBCSVN等方式

    @Configuration
    @EnableConfigurationProperties({SvnKitEnvironmentProperties.class, CredhubEnvironmentProperties.class, JdbcEnvironmentProperties.class, NativeEnvironmentProperties.class, VaultEnvironmentProperties.class})
    @Import({CompositeRepositoryConfiguration.class, JdbcRepositoryConfiguration.class, VaultConfiguration.class, VaultRepositoryConfiguration.class, CredhubConfiguration.class, CredhubRepositoryConfiguration.class, SvnRepositoryConfiguration.class, NativeRepositoryConfiguration.class, GitRepositoryConfiguration.class, DefaultRepositoryConfiguration.class})
    public class EnvironmentRepositoryConfiguration {
        // ...
    }
    

    查看 JdbcRepositoryConfiguration --> JdbcEnvironmentRepository --> EnvironmentRepository 可知,EnvironmentRepository 是核心接口,其下的实现有

    JdbcEnvironmentRepository
    
    EnvironmentRepository
    
    JGitEnvironmentRepository
    
    MultipleJGitEnvironmentRepository
    
    MultipleJGitEnvironmentRepositoryFactory
    
    EnvironmentRepositoryConfiguration
    
    DefaultRepositoryConfiguration
    

    为什么默认是 Git 作为配置仓库

    @Configuration
    @ConditionalOnMissingBean(value = EnvironmentRepository.class, search = SearchStrategy.CURRENT)
    class DefaultRepositoryConfiguration {
        ...
        @Bean
        public MultipleJGitEnvironmentRepository defaultEnvironmentRepository(
    	    MultipleJGitEnvironmentRepositoryFactory gitEnvironmentRepositoryFactory,
    	    MultipleJGitEnvironmentProperties environmentProperties) throws Exception {
    	return gitEnvironmentRepositoryFactory.build(environmentProperties);
        }
    }
    

    当 Spring 应用上下文没有出现 EnvironmentRepository Bean 的时候,那么,默认激活 DefaultRepositoryConfiguration (Git 实现)

    由此我们可以尝试下自定义 EnvironmentRepository 实现,用来替换默认的 JGitEnvironmentRepository

    package com.example.demo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.config.environment.Environment;
    import org.springframework.cloud.config.environment.PropertySource;
    import org.springframework.cloud.config.server.EnableConfigServer;
    import org.springframework.cloud.config.server.environment.EnvironmentRepository;
    import org.springframework.context.annotation.Bean;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    @SpringBootApplication
    @EnableConfigServer
    public class DemoApplication {
    
        public static void main(String[] args) {
    	SpringApplication.run(DemoApplication.class, args);
        }
    
        @Bean
        public EnvironmentRepository environmentRepository() {
    
    //      return new EnvironmentRepository() {
    //		@Override
    //		public Environment findOne(String application, String profile, String label) {
    //			return null;
    //		}
    //	};
    
    	return (String application, String profile, String label) -> {
    		Environment environment = new Environment("default", profile);
    		List<PropertySource> propertySources = environment.getPropertySources();
    		Map<String, Object> source = new HashMap<>();
    		source.put("name", "心灵蚂蚁");
    		PropertySource propertySource = new PropertySource("map", source);
    		propertySources.add(propertySource);
    		return environment;
    	};
        }
    
    }
    
    

    浏览器访问获取配置

    Spring Cloud Config

    为什么客户端获取配置时需要写成 /{application}/{profile}/{label} 的格式

    在类 EnvironmentController 中定义好的

    @RestController
    @RequestMapping(
        method = {RequestMethod.GET},
        path = {"${spring.cloud.config.server.prefix:}"}
    )
    public class EnvironmentController {
        // ...
        @RequestMapping(
            path = {"/{name}/{profiles}/{label:.*}"},
            produces = {"application/json"}
        )
        public Environment labelled(@PathVariable String name, @PathVariable String profiles, @PathVariable String label) {
            // ...
        }
    }
    

    PropertySourceLocator

    Spring Cloud 提供用于支持扩展自定义配置加载到spring Environment中。

    参考:https://www.cnblogs.com/lizo/p/7683300.html

  • 相关阅读:
    状压DP
    数位dp
    浅谈网络最大流
    Luogu p2456 二进制方程
    dp基础√
    双联通分量与二分图
    是时候再写一篇新的博客了
    神仙网络最大流
    状态压缩dp相关
    图论 test solution
  • 原文地址:https://www.cnblogs.com/linyuhong/p/14789315.html
Copyright © 2011-2022 走看看