如何建立自己的应用程序设置

时间:2010-05-22 01:41:16

标签: java design-patterns configuration

我想为我的应用程序构建一个ApplicationSettingApplicationSetting可以存储在属性文件或数据库表中。设置存储在键值对中。 E.g。

ftp.host = blade
ftp.username = dummy
ftp.pass = pass
content.row_pagination = 20
content.title = How to train your dragon.

我的设计如下:

应用程序设置阅读器:

    interface IApplicationSettingReader {
    Map read();
}

DatabaseApplicationSettingReader implements IApplicationSettingReader {
    dao appSettingDao;

    Map read() {
        List<AppSettingEntity> listEntity = appSettingsDao.findAll();
        Map<String, String> map = new HaspMap<String, String>();
        foreach (AppSettingEntity entity : listEntity) {
            map.put(entity.getConfigName(), entity.getConfigValue());
        }

        return new AppSettings(map);
    }
}

DatabaseApplicationSettingReader implements IApplicationSettingReader {
    dao appSettingDao;

    Map read() {
        //read from some properties file 
        return new AppSettings(map);
    }
}

应用程序设置类:

AppSettings {
private static AppSettings instance = new AppSettings();
private Map map;

private AppSettings() {
}



public static AppSettings getInstance() {
    if (instance == null) {
        throw new RuntimeException("Object not configure yet");
    } 

    return instance;
}

public static configure(IApplicationSettingReader reader) {
    this.map = reader.read();

}

public String getFtpSetting(String param) {
    return map.get("ftp." + param);
}

public String getContentSetting(String param) {
    return map.get("content." + param);
}

}

测试类:

AppSettingsTest {
    IApplicationSettingReader reader;

    @Before
    public void setUp() throws Exception {
        reader = new DatabaseApplicationSettingReader();
    }

    @Test
    public void  getContentSetting_should_get_content_title() {
        AppSettings.configure(reader);

        Instance settings = AppSettings.getInstance();
        String title = settings.getContentSetting("title");
        assertNotNull(title);
        Sysout(title);
    }

}

我的问题是:

  1. 你能否就我的代码发表意见,有什么不对吗?????

  2. 我配置了一次应用程序设置,在应用程序启动时,我使用适当的阅读器(DbReaderPropertiesReader)配置应用程序设置,我将其设为单例,因为应用程序只有一个ApplicationSettngs的实例。问题是,当某些用户直接将数据库或文件编辑到数据库或文件时,我无法获得更改的值。现在,我想实现像ApplicationSettingChangeListener这样的东西。因此,如果数据发生变化,我将刷新我的应用程序设置。你有什么建议可以实现吗????

2 个答案:

答案 0 :(得分:0)

我没有彻底检查过您的代码,但似乎存在并发问题。地图是线程不安全的(HashMap),所以如果你通过config()改变它并让其他线程访问map,你就会遇到问题。

虽然您可以使用ConcurrentHashMap代替HashMap,但ConcurrentHashMap上的批处理操作不是原子的。这意味着,如果您使用它,您将看到“中途”修改配置。根据您的应用程序,这可能不会好。

所以,解决方法就是使用它:

private volatile ImmutableMap map;

public config(){
    ImmutableMap newMap = createNewMap();
    this.map = newMap;
}

这将原子地改变你的配置(没有中间状态可见)。

至于动态更新配置,log4j使用监视配置文件的后台线程来完成。您当然可以通过定期轮询来监视数据库表。

在这种情况下,您的Config类最好有一个ScheduledExecutor,其任务将监视文件/ db并定期调用config()。

答案 1 :(得分:0)

问题#2的答案是使用一个线程并定期检查文件是否已更改,或者只是使用文件内容重新初始化您的设置。