一个java web项目启动时遇到了下面这么个报错:
问题是解决了,但是怎么会出现这么个报错?于是找到了配置文件的引入部分:
1 2 3 4 5 6 7 8 <bean  id ="propertyConfigurer"  class =     "org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer" > <property  name ="locations" > <list > </list > </property > </bean > 
这里解析配置文件用的是 PreferencesPlaceholderConfigurer 这个类,该类扩展了 PropertyPlaceholderConfigurer 类,添加了windows下用户路径和系统路径的解析。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 private  Preferences systemPrefs;private  Preferences userPrefs;@Override protected  String resolvePlaceholder (String placeholder, Properties props)  {String  path  =  null ;String  key  =  placeholder;int  endOfPath  =  placeholder.lastIndexOf('/' );if  (endOfPath != -1 ) {0 , endOfPath);1 );String  value  =  resolvePlaceholder(path, key, this .userPrefs);if  (value == null ) {this .systemPrefs);if  (value == null ) {return  value;
Preferences是一个保存系统和用户配置信息的一个类,同时有下面的子类扩展关系:
继续看 resolvePlaceholder 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 protected  String resolvePlaceholder (String path, String key,      Preferences preferences)  {if  (path != null ) {try  {if  (preferences.nodeExists(path)) {return  preferences.node(path).get(key, null );else  {return  null ;catch  (BackingStoreException ex) {throw  new  BeanDefinitionStoreException ("Cannot access specified node path ["  + path + "]" , ex);else  {return  preferences.get(key, null );
nodeExists 方法是 AbstractPreferences 中的一个判断系统路径是否存在的一个方法,追踪调用链可以发现这个方法最终调用了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 protected  String[] childrenNamesSpi() throws  BackingStoreException {int  nativeHandle  =  openKey(KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE);if  (nativeHandle == NULL_NATIVE_HANDLE) {throw  new  BackingStoreException ("Could not open windows registry node "  +" at root 0x"  +"." );
同时,在该类的定义中我们可以看到在windows中系统根路径被定义为:
1 2 private  static  final  byte [] WINDOWS_ROOT_PATH = "Software\\JavaSoft\\Prefs" );
这也就是为什么解决方法中需要添加这个注册表项了。
回过头再来看这个问题,首先配置文件key中出现了 / 符号,同时解析配置文件的类用了 PreferencesPlaceholderConfigurer 而不是常规的 PropertyPlaceholderConfigurer 导致Spring同时解析用户和系统环境中的配置,而windows中默认系统根路径注册表中不存在,这才导致了问题的产生。
按照道理来说这两个注册表项应该是jdk或者jre安装的时候创建的,于是google之,发现了下面的一个issue:https://bugs.openjdk.java.net/browse/JDK-8139507 
本站所有文章除特别声明外,均采用 BY-NC-SA 4.0  许可协议。转载请注明出处!