[Java] ResourceBundleのキャッシュ

2018年10月15日月曜日

Java

ResourceBundle.clearCache

プロパティファイルからのプロパティ読み込みの動作確認時にプロパティファイル自体を入れ替えて、確認しようとしたけど、最初はうまくいかなかった。

sample_test1.properties
sample1=Foo

sample_test2.properties
sample1=Bar

その1
        Path sample = Paths.get("sample.properties");
        Path test1 = Paths.get("sample_test1.properties");
        Files.copy(test1, sample, StandardCopyOption.REPLACE_EXISTING);

        ResourceBundle rb = ResourceBundle.getBundle("sample");
        String sample1 = rb.getString("sample1");
        // sample1 : "Foo"

        Path test2 = Paths.get("sample_test2.properties");
        Files.copy(test2, sample, StandardCopyOption.REPLACE_EXISTING);

        sample1 = rb.getString("sample1");
        // sample1 : "Foo"
        // sample1 : "Bar"になってくれない。

これはResourceBundleが値をキャッシュしているからだ。
であれば、ファイル入れ替え後にキャッシュをクリアすればいいはず。

https://docs.oracle.com/javase/jp/8/docs/api/java/util/ResourceBundle.html#clearCache--

その2
        Path sample = Paths.get("sample.properties");
        Path test1 = Paths.get("sample_test1.properties");
        Files.copy(test1, sample, StandardCopyOption.REPLACE_EXISTING);

        ResourceBundle rb = ResourceBundle.getBundle("sample");
        String sample1 = rb.getString("sample1");
        // sample1 : "Foo"

        Path test2 = Paths.get("sample_test2.properties");
        Files.copy(test2, sample, StandardCopyOption.REPLACE_EXISTING);

        ResourceBundle.clearCache();

        sample1 = rb.getString("sample1");
        // sample1 : "Foo"
        // sample1 : "Bar"になってくれない。

と思って、やってみたけど、クリアされない。

ResourceBundle.getBundle

clearCacheは保持している値のキャッシュをクリアするのではなく、ResourceBundleのインスタンスをクリアする。
clearCacheはインスタンスメソッドではなく、staticメソッドなので、その時点で気づくべきだけど。

なので、clearCacheした後に、再度getBundleでResourceBundleのインスタンスを再取得する必要がある。

その3
        Path sample = Paths.get("sample.properties");
        Path test1 = Paths.get("sample_test1.properties");
        Files.copy(test1, sample, StandardCopyOption.REPLACE_EXISTING);

        ResourceBundle rb = ResourceBundle.getBundle("sample");
        String sample1 = rb.getString("sample1");
        // sample1 : "Foo"

        Path test2 = Paths.get("sample_test2.properties");
        Files.copy(test2, sample, StandardCopyOption.REPLACE_EXISTING);

        ResourceBundle.clearCache();
        rb = ResourceBundle.getBundle("sample");

        sample1 = rb.getString("sample1");
        // sample1 : "Bar"

結局、ResourceBundleのインスタンスを使い回すデザインはあまり良くない。
ResourceBundle.getBundle自体がインスタンスをキャッシュしてくれるデザインなので、必要であれば、都度ResourceBundle.getBundleを呼べばいい。