我正在使用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");
它给出了同样的错误。
答案 0 :(得分:32)
暂时考虑一下你的问题。您不必在静态字段中保留application.properties
的任何属性。帕特里克建议的“解决方法”非常脏:
请记住,当您使用@Service
注释控制bean时,您将其创建委托给Spring容器。 Spring通过仅创建一个在整个应用程序中共享的bean来控制此bean生命周期(当然,您可以更改此行为,但我在此处引用默认行为)。在这种情况下,任何静态字段都没有意义 - Spring确保只有一个UserService
实例。并且您得到了您所描述的错误,因为静态字段初始化在Spring容器启动之前发生了许多处理器周期。您可以在此处找到有关when static fields are initialized的更多信息。
做这样的事情要好得多:
@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创建了great post on this subject on his blog,我建议您阅读它以获取更多信息。
如果您需要以某种方式在静态上下文中使用值,最好定义一些内部带有public static final
字段的公共类 - 这些值将在类加载器加载此类时实例化,并且在应用程序生命周期内不会被修改。唯一的问题是你无法从Spring的application.properties
文件加载这些值,你必须直接在代码中维护它们(或者你可以实现一些从属性文件中加载这些常量值的类,但这听起来对你要解决的问题非常冗长。)
答案 1 :(得分:9)
Spring不允许将值注入静态变量。
解决方法是创建一个非静态setter,将值分配给静态变量:
@Service
public class UserService {
private static String SVN_URL;
@Value("${SVN_URL}")
public void setSvnUrl(String svnUrl) {
SVN_URL = svnUrl;
}
}
答案 2 :(得分:3)
不允许访问静态成员函数中的application.properties,但这是一种解决方法,
server.ip = 127.0.0.1
public class PropertiesExtractor {
private static Properties properties;
static {
properties = new Properties();
URL url = new PropertiesExtractor().getClass().getClassLoader().getResource("application.properties");
try{
properties.load(new FileInputStream(url.getPath()));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static String getProperty(String key){
return properties.getProperty(key);
}
}
public class Main {
private static PropertiesExtractor propertiesExtractor;
static{
try {
propertiesExtractor = new PropertiesExtractor();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
public static getServerIP(){
System.out.println(propertiesExtractor.getProperty("server.ip")
}
}
答案 3 :(得分:0)
static String profile;
@Value("${spring.profiles.active:Unknown}")
private void activeProfile(String newprofile) {
profile = newprofile;
};