アノテーションの罠
アノテーションでリフレクションするコードを書いてそれをデバッグしていて気づいたのですが、コンテキストがリロード(Tomcatでデバッグだとプロジェクトのソースを改変すると起こります)されるとアノテーションクラスはあらたにクラスロードし直されるのか、同じアノテーションクラスではない、別もののクラスになっちゃいます。全くクラス名は一緒だしメンバーも一致しているのですが、クラスのIDが変わっているようです。Tomcatのコンテキストクラスローダと、JVM自体のアノテーションクラスのクラスローダで別物扱いにされているのかもしれない。
例えば以下の私のコードでコンテキストリロード後は、 == 比較の位置で、==も equals比較も一致しなくなります。
for (Method method: pageModel.getClass().getDeclaredMethods()) { for (Annotation annotation: method.getAnnotations()) { // ↓これが不一致に! if (annotation.annotationType() == Action.ActionHandler.class) { Action.ActionHandler actionAnnotation = (Action.ActionHandler)annotation; if (action.equals(actionAnnotation.action())) { return new HandlerInfo(actionAnnotation, method); } } } }
むりやり getName().equals() でクラス名の比較をすれば一致しますが、キャスト代入しようとした瞬間InvocationTargetExceptionで死んでしまいます。
リフレクションして得たものは既に、コンテキストリロード前の失われた型情報になってしまっているか、その逆にメソッドの方が変化したか、いずれにしてもうまくないです。アノテーションだからequalsをオーバーライド実装なんてできないですしequals実装しても代入できないからメンバをassignできるようにしなきゃいけないし…って、これもアノテーションだから結局できないという。。。困りました。
アノテーションオブジェクト自体にリフレクションでインボークという手しか残っていないかなー。きついですねー。なにか他に良い手はないものか…。コンテキストリロードをやめてjavaから立ち上げ直せば良いのだけどね。運用方法でカバーするしかないのかな。