如何将application.properties中的值赋给静态变量?
我正在使用Spring MVC。 我有一个用@Service
注释的UserService
类,它有很多静态变量。 我想用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
的Instantiation of bean failed; nested exception is java.lang.ExceptionInInitializerError
Instantiation of bean failed; nested exception is java.lang.ExceptionInInitializerError
我也试过@Autowired private static Environment env;
然后: private static String SVN_URL=env.getProperty("SVN_URL");
它给出了同样的错误。
想想你的问题一秒钟。 您不必在静态字段中保留application.properties
中的任何属性。 帕特里克建议的“解决方法”非常脏:
- 您不知道何时修改此静态字段
- 你不知道哪个线程修改了它的值
- 任何时候任何线程都可以改变这个静态字段的值,你就搞砸了
- 以这种方式初始化私有静态字段对我来说毫无意义
请记住,当您使用@Service
注释控制bean时,您将其创建委托给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
字段的公共类 – 这些值将在classloader加载此类时实例化,并且在应用程序生命周期内不会被修改。 唯一的问题是你无法从Spring的application.properties
文件加载这些值,你必须直接在代码中维护它们(或者你可以实现一些从属性文件加载这些常量值的类,但是这听起来对你要解决的问题非常冗长)。
Spring不允许将值注入静态变量。
解决方法是创建一个非静态setter,将您的值赋值给静态变量:
@Service public class UserService { private static String SVN_URL; @Value("${SVN_URL}") public void setSvnUrl(String svnUrl) { SVN_URL = svnUrl; } }