Bean Validation の isValid は、実装によってスレッドの安全性が保証されるべきって書いてあるけど、initialize でアノテーションのパラメータをインスタンス変数に保持するのはダメなの?という話。 https://t.co/M4uQGmFMuZ
— kntmr (@knt_mr) 2017年2月21日
一応、調べてみます。ドキュメントはこちら。
http://docs.oracle.com/javaee/7/api/javax/validation/ConstraintValidator.html
This method can be accessed concurrently, thread-safety must be ensured by the implementation.
バリデータのインスタンスは同一のものが使い回されるようです。そのため、isValid
はスレッドセーフに実装する必要があります。
で、アノテーションのパラメータを initialize
の中でインスタンス変数に保持するコードは割と一般的ですが、アノテーションのパラメータに異なる値を渡して検証する場合、isValid
の処理で不整合が発生しないんだろうか、ということを調べてみます。
こんなアノテーションを用意。param
でパラメータを取れるようにしておきます。
こんなバリデータを用意。initialize
でアノテーションのパラメータをインスタンス変数に保持して、isValid
で利用することを想定します。バリデーションロジックは適当です。
こんなテストコードを用意。Bean のフィールドに指定している @SampleValidation
には同じパラメータを渡します。
これを実行すると以下のように出力されます。同一のインスタンスが使われています。
@initialize : param=hoge, hashCode=1858609436 @isValid : param=hoge, hashCode=1858609436, value=bar @isValid : param=hoge, hashCode=1858609436, value=foo
次に、Bean のフィールドに指定しているアノテーションに別々のパラメータを渡します。
@SampleValidation(param = "hoge") private String name; @SampleValidation(param = "fuga") private String value;
で、先ほどのテストコードを実行すると以下のように出力されます。アノテーションごとに別々のインスタンスが使われるようになります。
@initialize : param=fuga, hashCode=1858609436 @isValid : param=fuga, hashCode=1858609436, value=bar @initialize : param=hoge, hashCode=786041152 @isValid : param=hoge, hashCode=786041152, value=foo
まとめ
アノテーションに別々のパラメータを渡すと、バリデータはアノテーションごとに別々のインスタンスが使われる。なるほど。
アノテーションのパラメータが違うならインスタンスは別物っぽい https://t.co/C7ZWsXmpqD
— kntmr (@knt_mr) 2017年2月21日