こんにちわ、みけです。
昨日に引き続いてアノテーションプロセッサーのあれをあれするあれです。
概要
- プロセッサーを指定する
- アノテーションプロセッサーにパラメーターを渡す
- プロセス対象のプロジェクトのリソースは取得できない
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ちゃんと嫁という話ですね…(´・ω・`)
おわり