Singletonパターンはクラスから一つしかオブジェクトが生成されないことを保証するパターンです。
SpringのControllerもSingletonパターンを実現しています。
Singletonではないクラスを書いた場合、たとえば1万人から要求があると、1万個のインスタンスを生成します。Javaでインスタンスの生成は、パフォーマンスを低下させる代表的な処理の一つです。そこでインスタンスを一つだけ生成しみんなで使いまわすことでパフォーマンスの低下と、メモリの圧迫を防ぎます。
ここで注意したいのが、Singletonのクラスにメンバー変数を指定することで、リクエスト間でインスタンスが共有され、ユーザAがメンバーXを変更した後に、ユーザBがメンバーXを書き換え、ユーザAがメンバーXを利用する・・・という障害が発生します。自分は現場に出てからずっとSpringにしか触れたことがないため、Controllerにメンバを指定しないのは「なんとなく当たり前」と思っていましたが、以外と知らない方が多いです。
- private static修飾子を指定した変数を宣言
- private修飾子を指定したコンストラクタを定義
- 変数に保持している唯一のオブジェクトを返すメソッドを定義
privateコンストラクタを定義することで、外部からのオブジェクト生成を不可能にして、オブジェクト生成は変数宣言時に初期化処理として1回だけ行う。作成された唯一のオブジェクトを外部から取得するために、 public static修飾子を指定したメソッドを定義し、変数で保持しているオブジェクトを返す。
シングルトンA
class SingletonA { private static SingletonA instance; private SingletonA() { } public static synchronized SingletonA getInstance() { if (instance == null) { instance = new SingletonA(); } return instance; } }
synchronized修飾子は、メソッドの同時実行を防ぐ排他制御を実現する修飾子で、インスタンスが2つ以上生成されるのを防ぐためにつけられています。
シングルトンB
class SingletonB { private static SingletonB instance = new SingletonB(); private SingletonB() { } public static SingletonB getInstance() { return instance; } }
ロード時にインスタンスが一回だけ作られる。
3年目の時に、5年目の先輩が別の開発PJに参画しており、
先輩:「あのPJでコンストラクタにprivateつけてたんだけど・・・。」
私 :「コンストラクタにprivateつけたらどうやってnewするんですか?」
先輩:「さぁ・・・。PJ中ずっと謎だった。」
なんてやり取りがありました。そのPJではSingletonを実装してたんですね。