こんにちわ、みけです。
昨日に引き続いてアノテーションプロセッサーのあれをあれするあれです。
概要
- プロセッサーを指定する
- アノテーションプロセッサーにパラメーターを渡す
- プロセス対象のプロジェクトのリソースは取得できない
1. プロセッサーを指定する
プロセッサーを指定する方法は次のとおり二つあります。
javacの-processorオプションで指定するsrc/main/resource/META-INF/services/javax.annotation.processing.Processorファイルで指定する
-processorオプションで指定する場合は次のように、
javac -processor jp.hoge.foo.BarProcessor,jp.hoge.foo.BasProcessor -classpath ...
カンマ区切りでプロセッサーのクラス名を指定します。
gradleで記述する場合は次のようになります。
compileJava {
options.compilerArgs += ['-processor', 'jp.hoge.foo.BarProcessor,jp.hoge.foo.BasProcessor']
}
プロセッサーの数が増えてくると、プロセッサーの実装の分だけ、
指定しないといけなくなるので、若干つらいかもしれません。
そこで、プロセッサー用のプロジェクトで、
サービスプロバイダーコンフィギュレーションファイル
に記述しておいた方がコンパイラーオプションが増えないので便利かもしれません。
サービスプロバイダーコンフィギュレーションファイルは、
META-INF/services/javax.annotation.processing.Processorというファイルで
プロセッサーのパッケージ名を含めた正規名を一行に一つ記入します。
例
jp.hoge.foo.BarProcessor jp.hoge.foo.BazProcessor
このファイルがある場合は、引数でプロセッサーを指定しなくても構いません。
2. アノテーションプロセッサーにパラメーターを渡す
プロセッサーの実装クラスには@SupportedOptionsアノテーションによって、
パラメーターを渡すことができます。
import javax.annotation.processing.SupportedOptions; @SupportedOptions({"foo", "bar"}) public class SampleProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { Map<String, String> options = processingEnv.getOptions(); String foo = options.getOrDefault("foo", "FOO"); String bar = options.getOrDefault("bar", "BAR"); } }
実際に渡されたパラメーターは、AbstractProcessorで宣言してある、
ProcessingEnvironment型のprocessingEnv変数から
#getOptions()メソッドで取得することができます。
パラメーターが指定されていない場合には、#getOptions()メソッドで
返されるMap<String, String>のキーに対して値は設定されていません。
例えば、上記の例でオプションfooに値が設定されていない場合は、
変数fooには"FOO"が設定されます。
パラメーターの設定方法は、javacコマンドの引数に-Aargument=valueの形で指定します。
例えば、foo、barに値を指定する場合は、次のようになります。
javac -Afoo=foofoo -Abar=barara ...
これをgradleで記述する場合は次のようになります。
compileJava {
options.compilerArgs += ['Afoo=foofoo', 'Abar=barara']
}
3. プロセス対象のプロジェクトのリソースは取得できない
これは単なる僕のポカミスで、アノテーションプロセッサーから、
コンパイル中のプロジェクトのリソースにアクセスできると
何故か思い込んでいて、
ずっと、「できない、できない…」と思ってたというだけの話です。
ファイルオブジェクトへのアクセスを可能にする
javax.annotation.processing.Filerという
インターフェースがあります。
そのインターフェースの下記の4つのメソッドによって、
ファイルへアクセスすることができます。
#createSourceFile(String, Element...)- ソースファイルの作成#createClassFile(String, Element...)- クラスファイルの作成#createResource(JavaFileManager.Location, String, String, Element...)- リソースファイルの作成#getResource(JavaFileManager.Location, String, String)- リソースファイルの取得
このときに、リソースファイルの取得メソッドがあるので、
勝つると思い込んでいたわけですが、
これはソースかクラスの出力先のディレクトリーにあるファイルに
アクセスできるだけで、
maven形式のディレクトリー構成のリソースファイル(src/main/resources)には
アクセスできません。
javadocちゃんと嫁という話ですね…(´・ω・`)
おわり