如何将 application.properties 中的值分配给静态变量? [英] How to assign a value from application.properties to a static variable?

查看:36
本文介绍了如何将 application.properties 中的值分配给静态变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using Spring MVC. I have a UserService class annotated with @Service that has a lot of static variables. I would like to instantiate them with values from the application.properties file.

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

For example in application.properties I have: SVN_URL = http://some.url/repositories

然后在类中有:@Value("${SVN_URL}") private static String SVN_URL

我得到bean的实例化失败;嵌套异常是 java.lang.ExceptionInInitializerError

我也试过@Autowired private static Environment env;

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

它给出了同样的错误.

推荐答案

考虑一下您的问题.您不必在静态字段中保留 application.properties 中的任何属性.帕特里克建议的解决方法"非常脏:

Think about your problem for a second. You don't have to keep any properties from application.properties in static fields. The "workaround" suggested by Patrick is very dirty:

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

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

Keep in mind that when you have bean controlled by @Service annotation you delegate its creation to Spring container. Spring controls this bean lifecycle by creating only one bean that is shared across the whole application (of course you can change this behavior, but I refer to a default one here). In this case any static field has no sense - Spring makes sure that there is only one instance of UserService. And you get the error you have described, because static fields initialization happens many processor-cycles before Spring containers starts up. Here you can find more about when static fields are initialized.

做这样的事情会好得多:

It would be much better to do something like this:

@Service
public class UserService {
    private final String svnUrl;

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

由于以下几个原因,这种方法更好:

This approach is better for a few reasons:

  • 构造函数注入直接描述了初始化对象所需的值
  • final 字段表示该值在构造函数调用中初始化后不会更改(您是线程安全的)
  • constructor injection describes directly what values are needed to initialize the object
  • final field means that this value wont be changed after it gets initialized in a constructor call (you are thread safe)

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

There is also another way to load multiple properties to a single class. It requires using prefix for all values you want to load to your configuration class. Consider following example:

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

    private String svnUrl;

    private int somePort;

    // ... getters and setters
}

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

Spring will handle TestProperties class initialization (it will create a testProperties bean) and you can inject this object to any other bean initialized by Spring container. And here is what exemplary application.properties file look like:

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

Baeldung 在他的博客上创建了一篇关于这个主题的很棒的帖子,我建议阅读它以获取更多信息.

Baeldung created a great post on this subject on his blog, I recommend reading it for more information.

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

If you need somehow to use values in static context it's better to define some public class with public static final fields inside - those values will be instantiated when classloader loads this class and they wont be modified during application lifetime. The only problem is that you won't be able to load these values from Spring's application.properties file, you will have to maintain them directly in the code (or you could implement some class that loads values for these constants from properties file, but this sounds so verbose to the problem you are trying to solve).

这篇关于如何将 application.properties 中的值分配给静态变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆