• Springboot热部署原理


    一、配置加载

        public static void main(String[] args) {
            ConfigurableApplicationContext ctx = SpringApplication.run(SampleTomcatApplication.class, args);
            String foo = ctx.getEnvironment().getProperty("foo");
            System.out.println(foo);
        }

    打印结果

    aaa,bbb

    源码解析

    1、我们在idea环境配置的参数Program arguments上配置的参数,就会被传进main方法的args中

        //封装命令行参数
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        
        public DefaultApplicationArguments(String... args) {
            Assert.notNull(args, "Args must not be null");
            this.source = new Source(args);
            this.args = args;
        }
        Source(String[] args) {
            super(args);
        }
        public SimpleCommandLinePropertySource(String... args) {
            super(new SimpleCommandLineArgsParser().parse(args));
        }
        //解析命令行参数
        public CommandLineArgs parse(String... args) {
            CommandLineArgs commandLineArgs = new CommandLineArgs();
            for (String arg : args) {
                //固定格式
                if (arg.startsWith("--")) {
                    String optionText = arg.substring(2);
                    String optionName;
                    String optionValue = null;
                    int indexOfEqualsSign = optionText.indexOf('=');
                    if (indexOfEqualsSign > -1) {
                        optionName = optionText.substring(0, indexOfEqualsSign);
                        optionValue = optionText.substring(indexOfEqualsSign + 1);
                    }
                    else {
                        optionName = optionText;
                    }
                    if (optionName.isEmpty()) {
                        throw new IllegalArgumentException("Invalid argument syntax: " + arg);
                    }
                    commandLineArgs.addOptionArg(optionName, optionValue);
                }
                else {
                    commandLineArgs.addNonOptionArg(arg);
                }
            }
            return commandLineArgs;
        }

    解析完命令行参数,最终放入到了PropertySource的source属性中,代码就不放了

    2、构建环境

    ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
            //创建并配置相应的环境,获取对应的ConfigurableEnvironment
            ConfigurableEnvironment environment = getOrCreateEnvironment();
            //根据用户配置,配置 environment系统环境
            configureEnvironment(environment, applicationArguments.getSourceArgs());

    创建环境

    //根据环境创建对应ConfigurableEnvironment
        private ConfigurableEnvironment getOrCreateEnvironment() {
            if (this.environment != null) {
                return this.environment;
            }
            switch (this.webApplicationType) {
            case SERVLET://Web程序
                return new StandardServletEnvironment();
            case REACTIVE://响应式web环境
                return new StandardReactiveWebEnvironment();
            default://普通程序
                return new StandardEnvironment();
            }
        }

    都继承自AbstractEnvironment

    public abstract class AbstractEnvironment implements ConfigurableEnvironment {
        
        //初始化配置文件source对象
        private final MutablePropertySources propertySources = new MutablePropertySources();
        
        //初始化了配置文件解析器
        private final ConfigurablePropertyResolver propertyResolver =
                new PropertySourcesPropertyResolver(this.propertySources);
    
        ···
    }

    解析配置文件,并配置到环境中

        protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
            if (this.addConversionService) {
                ConversionService conversionService = ApplicationConversionService.getSharedInstance();
                environment.setConversionService((ConfigurableConversionService) conversionService);
            }
            // 将main 函数的args封装成 SimpleCommandLinePropertySource 加入environment中。
            configurePropertySources(environment, args);
            // 激活相应的配置文件
            configureProfiles(environment, args);
        }
        
        protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
            MutablePropertySources sources = environment.getPropertySources();
            if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {
                sources.addLast(new MapPropertySource("defaultProperties", this.defaultProperties));
            }
            if (this.addCommandLineProperties && args.length > 0) {
                String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
                if (sources.contains(name)) {
                    PropertySource<?> source = sources.get(name);
                    CompositePropertySource composite = new CompositePropertySource(name);
                    //解析args,并设置到source属性中,SimpleCommandLinePropertySource继承自PropertySource
                    composite.addPropertySource(
                            new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
                    composite.addPropertySource(source);
                    //存在覆盖的参数,则替换
                    sources.replace(name, composite);
                } else {
                    //解析并设置参数到环境中
                    sources.addFirst(new SimpleCommandLinePropertySource(args));
                }
            }
        }

    获取配置文件属性String foo = ctx.getEnvironment().getProperty("foo");

        public String getProperty(String key) {
            return this.propertyResolver.getProperty(key);
        }

    走的就是AbstractEnvironment方法,通过ConfigurablePropertyResolver的方法获取,具体获取源码也不看了。

    二、热部署

    jar包依赖

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

  • 相关阅读:
    去除字符串重复数据 分类: python基础学习 2013-08-08 17:43 171人阅读 评论(0) 收藏
    python中计时工具timeit模块的基本用法 分类: python python基础学习 2013-08-08 10:05 2072人阅读 评论(0) 收藏
    socket通信简介 分类: socket 2013-08-06 17:49 209人阅读 评论(0) 收藏
    AF_INET和PF_INET的细微不同 分类: socket 2013-08-06 17:35 264人阅读 评论(0) 收藏
    查看linux操作系统版本号 分类: ubuntu 2013-08-05 10:14 265人阅读 评论(0) 收藏
    python yield生成器 分类: python基础学习 2013-08-04 15:40 324人阅读 评论(0) 收藏
    html 元素 2013-08-04 14:53 236人阅读 评论(0) 收藏
    UTF8默认编码下的MYSQL命令框中输入汉字显示乱码的问题 分类: 测试 2013-08-02 14:16 371人阅读 评论(0) 收藏
    os.path模块学习 2013-07-30 17:46 193人阅读 评论(0) 收藏
    python 操作windows下的目录 分类: python python基础学习 2013-07-30 17:30 274人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/sglx/p/15673243.html
Copyright © 2020-2023  润新知