为什么运行jar包时spring.proflies.active=×××配置不同环境无效

背景

在最近的一个项目中,因为开发环境和测试环境的配置差异很大,就想着不同环境做不同的配置,在启动时候选择具体的环境就可以了。配置如下图:

实操

配置完成后commit,push,合并到master(听说10.1后就会是main了),测试环境拉代码build,感觉稳如老狗,结果却是出乎意料,spring.proflies.active=dev没起作用,自己在本地电脑打包以后,用命令行启动,发现本应是

The following profiles are active: dev

结果却是

No active profile set, falling back to default profiles: default

这就说明spring.proflies.active这个变量并没有传递到启动的环境参数中,这是怎么回事了?这个问题在我的第一个项目中也遇到过,当时是稀里糊涂的就过去了,也没有细究,这次我决定一定要一劳永逸的解决这个问题。

解决

于是打开Google,开启查找模式,经历了多次的尝试过后,最后找见原因所在,在spring应用的入口处的run方法没有传递参数导致的,赶紧在run方法加上参数,再进行尝试,达到预想的结果。

之前的代码

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class);
    }
}

加入参数后

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

探究

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
        return run(new Class[]{primarySource}, args);
    }

    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        //run函数包含参数
        return (new SpringApplication(primarySources)).run(args);
    }

SpringApplication.run方法包含两个参数,第一个是primarySource,接受一个容器的配置类,也可以说是程序的入口类,第二个参数args就是我丢掉的命令行参数,命令行参数传入到SpringApplication中,用命令行启动时,依据参数加载对应的配置。

下面是SpringApplication的构造函数(new SpringApplication(primarySources))。

主要是

/**
	 * Run the Spring application, creating and refreshing a new
	 * {@link ApplicationContext}.
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return a running {@link ApplicationContext}
	 */
	public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

DefaultApplicationArguments构造方法

public class DefaultApplicationArguments implements ApplicationArguments {

	private final Source source;

	private final String[] args;

	public DefaultApplicationArguments(String... args) {
		Assert.notNull(args, "Args must not be null");
		this.source = new Source(args);
		this.args = args;
	}

	//中间的省略

	private static class Source extends SimpleCommandLinePropertySource {

		Source(String[] args) {
			super(args);
		}

		@Override
		public List<String> getNonOptionArgs() {
			return super.getNonOptionArgs();
		}

		@Override
		public List<String> getOptionValues(String name) {
			return super.getOptionValues(name);
		}

	}

}

args参数在构造方法中在作为参数放到了DefaultApplicationArguments的静态内部类Source的构造方法中进一步封装,至于下面的全局变量args放的就是原始的args参数。可以通过getSourceArgs方法得到。

参数解析

在父类SimpleCommandLinePropertySource的构造方法中new了一个SimpleCommandLineArgsParser对象,然后调用parse()方法解析参数

public CommandLineArgs parse(String... args) {
        CommandLineArgs commandLineArgs = new CommandLineArgs();
        String[] var3 = args;
        int var4 = args.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String arg = var3[var5];
            if (arg.startsWith("--")) {
                String optionText = arg.substring(2);
                String optionValue = null;
                int indexOfEqualsSign = optionText.indexOf(61);
                String optionName;
                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;
    }

参考

https://blog.csdn.net/yhahaha_/article/details/88899330SpringBoot(九)启动流程分析之命令行参数args的封装解析

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值