コントローラクラスのstatic変数で params
やrequest
などのオブジェクトが定義されており、playframework1ではコントローラクラスのオブジェクトがリクエスト毎に生成される方式は採用されていない。
アクションメソッドをstaticで記述するルールなのでそこから自由に参照できるためにも、このようなスタイルを採用したのかな、とか想像。
static変数はJVMごとのスコープなのでリクエスト毎に異なる値を保持することは不可能。実際に変数へアクセスする際はThreadLocal
クラスによりスレッドごとに参照されるオブジェクトが切り替わるような仕組みが暗黙的に働くようになっている。
発動する条件は下記に書かれている。
/**
* Check if a field must be translated to a 'thread safe field'
*/
static boolean isThreadedFieldAccess(CtField field) {
if (field.getDeclaringClass().getName().equals("play.mvc.Controller") || field.getDeclaringClass().getName().equals("play.mvc.WebSocketController")) {
return field.getName().equals("params")
|| field.getName().equals("request")
|| field.getName().equals("response")
|| field.getName().equals("session")
|| field.getName().equals("params")
|| field.getName().equals("renderArgs")
|| field.getName().equals("routeArgs")
|| field.getName().equals("validation")
|| field.getName().equals("inbound")
|| field.getName().equals("outbound")
|| field.getName().equals("flash");
}
return false;
}
Javaの言語仕様をからするとギョッとするような記述なので拒絶反応を示す人も多いと思う。こうゆうものと納得するしかない。
ここに当てはまるstatic変数はスレッドごとに参照されるが、それ以外は言語仕様通りのstatic変数として振る舞う。
調子に乗ってstatic変数を作ってスレッド変数のように扱ってはいけない。