【问题标题】:Spring Boot get spring.profiles.active value in a static blockSpring Boot 在静态块中获取 spring.profiles.active 值
【发布时间】:2021-03-15 04:18:31
【问题描述】:

是否可以在某个类的静态块中获取spring active profile的值?

我已经尝试@value("$(spring.profiles.active)")@Autowired Environment env; 来获取值,但在静态块内都导致为空。

我知道静态块是在 bean 加载期间的 spring 初始化之前执行的,那么是否有任何解决方法可以从静态块内的 application.yml 获取活动配置文件值或任何值?

示例代码:

@Value("$(spring.profiles.active)")
private String env;

static {
        URL url = null;
        WebServiceException e = null;
        try {
            ClassPathResource wsdlLoc = new ClassPathResource("/wsdl/Transaction_"+env+".wsdl");
            url = new URL(wsdlLoc.getURL().toString());
        } catch (IOException ex) {
            e = new WebServiceException(ex);
        }
        TRANSACTIONPROCESSOR_WSDL_LOCATION = url;
        TRANSACTIONPROCESSOR_EXCEPTION = e;
    }

【问题讨论】:

  • 您希望在构造类的实例之后设置的变量在在加载类时可用吗?并不是说这会首先编译。只需放弃所有静态业务,并在构造函数中初始化所有实例变量。
  • 你是对的。但这是 wsimport 为 Jax ws 创建的客户端存根。我无法删除静态块,因为我将不得不使其他被覆盖的方法也变成非静态的,这与超类 javax.xml.ws.Service 不兼容。

标签: java spring spring-boot properties


【解决方案1】:

请使用下面的静态工具获取环境变量

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.DisposableBean;

@Service
@Lazy(false)
public class SpringContextHolder implements ApplicationContextAware, DisposableBean{
    private static ApplicationContext applicationContext = null;

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static void clearHolder() {
        applicationContext = null;
    }

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

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextHolder.applicationContext = applicationContext;
    }
}

如何使用

import org.springframework.core.env.Environment;

//--- pass some code
@SpringBootApplication
public class MyApplication {

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

        Environment environment = SpringContextHolder.getApplicationContext().getEnvironment();
        System.out.println(environment.getProperty("spring.profiles.active"));
    }

}


【讨论】:

  • 这导致了 java.lang.ExceptionInInitializerError。 SpringContextHolder.getApplicationContext() 为空;
  • 调用静态代码应该在 SpringApplication.run() 之后。我修改代码示例以清晰显示。
  • 成功了!!我将 @Lazy(true) 添加到具有静态块的类中,并确保在它之前加载 SpringContextHolder。非常感谢。
【解决方案2】:

AFAIK 这是不可能的,不应使用..

混合静态上下文和依赖注入框架的上下文是一种反模式。

根据您要注入环境的位置,这应该不会有太大的区别,因为 Spring 会将您的组件/服务作为注入上下文中的单例处理。

总结:不要在 Spring 应用程序中使用大量静态上下文

【讨论】:

  • 我同意。但这是由 wsimport 生成的 Jaxws 客户端存根。我只想根据环境更改运行时的 WSDL 文件位置。
猜你喜欢
  • 2022-07-13
  • 1970-01-01
  • 1970-01-01
  • 2021-01-09
  • 2017-05-27
  • 2016-01-20
  • 2016-10-01
  • 2018-02-10
  • 1970-01-01
相关资源
最近更新 更多