1. 程式人生 > 其它 >SpringBoot中獲取spring.profiles.active的值

SpringBoot中獲取spring.profiles.active的值

SpringBoot通過@Profile("dev") 可以在配置類中限定配置環境,在實際開發中可能需要方法級別的控制,也就是說獲取到當前環境的具體資訊

最終通過檢視SpringBoot日誌以及原始碼找到答案

  • SpringBoot啟動日誌中有下面這句:
15:57:56.128 [restartedMain] INFO  c.d.o.OptplatformApplication - The following profiles are active: dev
  • 跟蹤程式碼:SpringApplication.run方法
public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        FailureAnalyzers analyzers = null;
        configureHeadlessProperty();
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting();
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
            ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
            Banner printedBanner = printBanner(environment);
            context = createApplicationContext();
            analyzers = new FailureAnalyzers(context);
            prepareContext(context, environment, listeners, applicationArguments,
                    printedBanner);  // 在這裡列印了,跟蹤進去
            refreshContext(context);
            afterRefresh(context, applicationArguments);
            listeners.finished(context, null);
            stopWatch.stop();
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass)
                        .logStarted(getApplicationLog(), stopWatch);
            }
            return context;
        }
        catch (Throwable ex) {
            handleRunFailure(context, listeners, analyzers, ex);
            throw new IllegalStateException(ex);
        }
    }
  • 跟蹤程式碼:SpringApplication.prepareContext方法
private void prepareContext(ConfigurableApplicationContext context,
      ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments, Banner printedBanner) {
   context.setEnvironment(environment);
   postProcessApplicationContext(context);
   applyInitializers(context);
   listeners.contextPrepared(context);
   if (this.logStartupInfo) {
      logStartupInfo(context.getParent() == null);
      logStartupProfileInfo(context);  // 名稱很明顯,繼續跟蹤進去
   }
   ......
}
  • 跟蹤程式碼:SpringApplication.logStartupProfileInfo方法
protected void logStartupProfileInfo(ConfigurableApplicationContext context) { 
   Log log = getApplicationLog();
   if (log.isInfoEnabled()) {
      String[] activeProfiles = context.getEnvironment().getActiveProfiles();
      if (ObjectUtils.isEmpty(activeProfiles)) {
         String[] defaultProfiles = context.getEnvironment().getDefaultProfiles();
         log.info("No active profile set, falling back to default profiles: "
               + StringUtils.arrayToCommaDelimitedString(defaultProfiles)); 
      }
      else {
         log.info("The following profiles are active: "
               + StringUtils.arrayToCommaDelimitedString(activeProfiles));  //找到了,很明顯用了ApplicationContxt容器,接下來就是寫個工具類來獲取Application就行啦。
 
     }
   }
}
  • 編寫SpringContextHolder工具類
@Slf4j
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {

    private static ApplicationContext applicationContext = null;

    /**
     * 取得儲存在靜態變數中的ApplicationContext.
     */
    public static ApplicationContext getApplicationContext() {
        assertContextInjected();
        return applicationContext;
    }

    /**
     * 從靜態變數applicationContext中取得Bean, 自動轉型為所賦值物件的型別.
     */
    public static <T> T getBean(String name) {
        assertContextInjected();
        return (T) applicationContext.getBean(name);
    }

    /**
     * 從靜態變數applicationContext中取得Bean, 自動轉型為所賦值物件的型別.
     */
    public static <T> T getBean(Class<T> requiredType) {
        assertContextInjected();
        return applicationContext.getBean(requiredType);
    }

    /**
     * 檢查ApplicationContext不為空.
     */
    private static void assertContextInjected() {
        if (applicationContext == null) {
            throw new IllegalStateException("applicaisetApplicationContexttonContext屬性未注入, 請在applicationContext" +
                    ".xml中定義SpringContextHolder或在SpringBoot啟動類中註冊SpringContextHolder.");
        }
    }

    /**
     * 獲取當前環境
     * @return
     */
    public static String getActiveProfile() {
        return applicationContext.getEnvironment().getActiveProfiles()[0];
    }

    /**
     * 清除SpringContextHolder中的ApplicationContext為Null.
     */
    public static void clearHolder() {
        log.debug("清除SpringContextHolder中的ApplicationContext:"
                + applicationContext);
        applicationContext = null;
    }

    @Override
    public void destroy() throws Exception {
        SpringContextHolder.clearHolder();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringContextHolder.applicationContext != null) {
            log.warn("SpringContextHolder中的ApplicationContext被覆蓋, 原有ApplicationContext為:" + SpringContextHolder.applicationContext);
        }
        SpringContextHolder.applicationContext = applicationContext;
    }
}
  • 使用示例

可以通過改方式來控制在測試環境打印出當前訪問的介面URL

  if ("dev".equals(SpringContextHolder.getActiveProfile())) {
            System.out.println(String.format("====當前介面URL: %s", request.getRequestURL()));
        }
   轉自:https://www.jianshu.com/p/a97aba019b3c