我正在使用Spring MVC。我有一个UserService带有@Service很多静态变量的注释类。我想使用application.properties文件中的值实例化它们。
UserService
@Service
例如在application.properties中,我有: SVN_URL = http://some.url/repositories
application.properties
SVN_URL = http://some.url/repositories
然后在课堂上是: @Value("${SVN_URL}") private static String SVN_URL
@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
我也尝试过 @Autowired private static Environment env;
@Autowired private static Environment env;
接着: private static String SVN_URL=env.getProperty("SVN_URL");
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类初始化(它将创建一个testPropertiesbean),并且你可以将该对象注入到其他由Spring容器初始化的bean中。这是示例application.properties文件的样子:
TestProperties
testPropertiesbean
test.svnUrl=https://svn.localhost.com/repo/ test.somePort=8080
替代解决方案 如果你需要以某种方式在静态上下文中使用值,则最好定义一些带有public static final内部字段的公共类-这些值将在类加载器加载此类时实例化,并且在应用程序生存期内不会被修改。唯一的问题是你将无法从Spring的application.properties文件中加载这些值,你将不得不直接在代码中维护它们(或者你可以实现一些类,以从属性文件中加载这些常量的值,但这听起来如此详细说明你要解决的问题)。