如何将 application.properties 中的值赋给静态变量?

2022-08-31 20:48:42

我正在使用Spring MVC。我有一个带注释的类,它有很多静态变量。我想使用 application.properties 文件中的值实例化它们。UserService@Service

例如,在 application.properties 中,我有:SVN_URL = http://some.url/repositories

然后在课堂上有:@Value("${SVN_URL}") private static String SVN_URL

我得到Instantiation of bean failed; nested exception is java.lang.ExceptionInInitializerError

我也试过@Autowired private static Environment env;

然后:private static String SVN_URL=env.getProperty("SVN_URL");

它给出了相同的错误。


答案 1

想一想你的问题。您不必在静态字段中保留任何属性。Patrick建议的“解决方法”非常肮脏:application.properties

  • 您不知道何时修改此静态字段
  • 你不知道哪个线程修改了它的值
  • 任何线程在任何时候都可以改变这个静态场的值,你被拧紧了
  • 以这种方式初始化私有静态字段对我来说毫无意义

请记住,当您通过注释控制Bean时,将其创建委托给Spring容器。Spring 通过仅创建一个在整个应用程序中共享的 Bean 来控制此 Bean 生命周期(当然,您可以更改此行为,但我在这里指的是默认行为)。在这种情况下,任何静态场都没有意义 - Spring确保只有一个实例。你会得到你所描述的错误,因为在Spring容器启动之前,静态字段初始化会发生许多处理器周期。在这里,您可以找到有关何时初始化静态字段的更多信息@ServiceUserService

建议

做这样的事情会好得多:

@Service
public class UserService {
    private final String svnUrl;

    @Autowired
    public UserService(@Value("${SVN_URL}") String svnUrl) {
        this.svnUrl = svnUrl;
    }
}

这种方法更好,原因如下:

  • 构造函数注入直接描述初始化对象所需的值
  • final字段表示此值在构造函数调用中初始化后不会更改(您是线程安全的)

@ConfigurationProperties

还有另一种方法可以将多个属性加载到单个类。它需要对要加载到配置类的所有值使用前缀。请考虑以下示例:

@ConfigurationProperties(prefix = "test")
public class TestProperties {

    private String svnUrl;

    private int somePort;

    // ... getters and setters
}

Spring将处理类初始化(它将创建一个bean),您可以将此对象注入到由Spring容器初始化的任何其他Bean中。下面是示例文件的样子:TestPropertiestestPropertiesapplication.properties

test.svnUrl=https://svn.localhost.com/repo/
test.somePort=8080

Baeldung在他的博客上创建了一个关于这个主题的精彩文章,我建议阅读它以获取更多信息。

替代解决方案

如果您需要以某种方式在静态上下文中使用值,则最好定义一些包含字段的公共类 - 这些值将在类装入器加载此类时实例化,并且在应用程序生存期内不会被修改。唯一的问题是你无法从Spring的文件中加载这些值,你必须直接在代码中维护它们(或者你可以实现一些从属性文件加载这些常量值的类,但这听起来很冗长,因为你试图解决的问题)。public static finalapplication.properties


答案 2

Spring不允许将值注入静态变量。

解决方法是创建一个非静态 setter,以将值分配到静态变量中:

@Service
public class UserService {

    private static String SVN_URL;

    @Value("${SVN_URL}")
    public void setSvnUrl(String svnUrl) {
        SVN_URL = svnUrl;
    }

}

推荐