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

新手上路,请多包涵

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

例如在 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");

它给出了同样的错误。

原文由 dannemp 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 821
2 个回答

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

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

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

建议

做这样的事情会更好:

 @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 将处理 TestProperties 类初始化(它将创建一个 testProperties bean),您可以将此对象注入由 Spring 容器初始化的任何其他 bean。这是示例 application.properties 文件的样子:

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

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

替代解决方案

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

原文由 Szymon Stepniak 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

解决方法是创建一个非静态设置器以将您的值分配给静态变量:

 @Service
public class UserService {

    private static String SVN_URL;

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

}

原文由 Patrick 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题