Java中如何从.yaml文件加载配置到类?使用SnakeYaml遇报错
问题:SnakeYAML加载YAML配置报错
使用SnakeYAML库加载.yaml配置文件时,抛出NoSuchMethodException: com.example.Settings$Database.<init>()错误。
我的Settings类代码
package com.example; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import org.yaml.snakeyaml.Yaml; public class Settings { private final static InputStream file; private final static Settings parsedSettings; public Database database; static { try { file = new FileInputStream("./src/main/java/com/example/settings.yaml"); Yaml yaml = new Yaml(); parsedSettings = yaml.loadAs(file, Settings.class); } catch(FileNotFoundException ex) { ex.printStackTrace(); throw new RuntimeException("Settings file not found or cannot be readed"); } } public Settings(){ this.database = parsedSettings.database; } public class Database { private String driver; private String user; private String password; private String host; private int port; private String name; private Database(String driver, String user, String password, String host, int port, String name){ this.driver = driver; this.user = user; this.password = password; this.host = host; this.port = port; this.name = name; } public String getDriver() { return this.driver; } public String getUser() { return this.user; } public String getPassword() { return this.password; } public String getHost() { return this.host; } public int getPort() { return this.port; } public String getDatabaseName() { return this.name; } } }
我的settings.yaml配置
database: driver: mysql user: root password: host: localhost port: 3306 name: java_messages_app
目前未使用任何框架,仅依赖第三方库,不确定该用静态方式还是构造方法加载配置,请求解决问题。
解决方案
1. 修复内部类核心问题
报错的根本原因有两个:
Database是非静态内部类,SnakeYAML无法直接实例化(非静态内部类依赖外部类实例)Database仅提供带参构造,SnakeYAML反射实例化对象时需要无参构造
修改后的Database类:
public static class Database { private String driver; private String user; private String password; private String host; private int port; private String name; // 添加无参构造方法 public Database() {} private Database(String driver, String user, String password, String host, int port, String name){ this.driver = driver; this.user = user; this.password = password; this.host = host; this.port = port; this.name = name; } // 原有getter方法保留 public String getDriver() { return this.driver; } public String getUser() { return this.user; } public String getPassword() { return this.password; } public String getHost() { return this.host; } public int getPort() { return this.port; } public String getDatabaseName() { return this.name; } }
2. 优化配置加载逻辑
原静态代码块存在资源泄漏(InputStream未关闭)、类加载异常风险高的问题,建议改成懒加载单例模式,保证配置仅加载一次且资源处理更安全:
package com.example; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import org.yaml.snakeyaml.Yaml; public class Settings { private static Settings instance; public Database database; // 私有构造,禁止外部直接实例化 private Settings() {} // 线程安全的懒加载获取实例 public static synchronized Settings getInstance() { if (instance == null) { // 使用try-with-resources自动关闭流 try (InputStream file = new FileInputStream("./src/main/java/com/example/settings.yaml")) { Yaml yaml = new Yaml(); instance = yaml.loadAs(file, Settings.class); } catch (FileNotFoundException ex) { ex.printStackTrace(); throw new RuntimeException("Settings file not found or cannot be read"); } catch (IOException ex) { ex.printStackTrace(); throw new RuntimeException("Failed to read settings file"); } } return instance; } public static class Database { private String driver; private String user; private String password; private String host; private int port; private String name; public Database() {} // getter方法保留 public String getDriver() { return driver; } public String getUser() { return user; } public String getPassword() { return password; } public String getHost() { return host; } public int getPort() { return port; } public String getDatabaseName() { return name; } } }
3. 使用方式
后续在代码中通过单例方法获取配置实例:
Settings settings = Settings.getInstance(); System.out.println(settings.database.getDatabaseName()); // 输出java_messages_app
内容的提问来源于stack exchange,提问作者otaxhu
相关产品推荐
相关产品推荐

