Propertiesをnative2asciiを使わずに使用するアスペクト
Javaを触ったことがある人ならpropertiesを1度や2度触ったことがあると思います。
設定ファイルを書いて、
native2ascii prop_jp.properties prop.properties
とか毎回やる訳です。
これ面倒だよなぁと調べてみたら、Java SE 6からはnative2asciiを使用しなくてもpropertiesを使えるようです。
本来なら、既存ソースのProperties.load(InputStream)をProperties.load(Reader)でラップするのですが、
ここはあえてアスペクトで同じことをしてみます。*1
コード
App.java
package sinsoku.propwrapper; import java.io.FileInputStream; import java.util.Properties; public class App { public static void main(String[] args) { try { Properties prop = new Properties(); prop.load(new FileInputStream("src/main/resources/prop.properties")); System.out.println(prop.getProperty("key")); System.out.println(prop.getProperty("日本語キー")); } catch (Exception e) { e.printStackTrace(); } } }
prop.properties
key=はろーわーるど 日本語キー=Hello World
出力結果
?????[???[???? null
処理は簡単すぎるので、解説は特に不要でしょう。
出力結果を見て分かるように、文字化けしたり、nullになったりしています。
PropertiesWrapper
package sinsoku.propwrapper; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.Properties; public aspect PropertiesWrapper { // Properties.load(InputStream)の呼び出しポイントを定義しています。 // また、引数がある場合はargs(変数名)が必要です。 pointcut loadpoint(InputStream inStream) : call (void Properties.load(InputStream)) && args(inStream); /** * <code>around</code>を指定しているため、既存の<code>Properties.load(InputStream)</code> * の代わりに実行されます。 * * @param inStream * <code>Properties.load(InputStream)</code>の引数のインスタンス */ void around(InputStream inStream) : loadpoint(inStream) { // ReaderでInputStreamをラップする。 Reader r = new InputStreamReader(inStream); // Propertiesインスタンスを取得する。 Properties prop = (Properties) thisJoinPoint.getTarget(); try { // Readerでラップしているので、日本語key/valueでも大丈夫 prop.load(r); } catch (IOException e) { e.printStackTrace(); } } }
出力結果
はろーわーるど Hello World
上手くアスペクトが織り込まれ、出力結果が文字化けせず表示されました。
アスペクトの処理としては、App.javaのProperties.load(InputStream)を実行せず、アドバイスの処理で置き換えています。
このポイントカットの指定だと、プロジェクトのソース全体のProperties.loadを置き換えることが出来ます。