最初に小さな修正
最初にいくつかの仮定を確認しましょう。詳細については、投稿の残りの部分で説明します。
私たちが知っているように、 init() はコンストラクターの仕事をします
いいえ、そうではありません。次のように大きく異なります。
- を宣言します
throws ServletException
。
- パラメータを宣言し
ServletConfig
、 * その親コンストラクタを呼び出します (Java がデフォルトで親の引数なしコンストラクタを呼び出すため)。
その最後の点については、何もしないので、一般的なケースでは問題にServlet
なりませんが、これらの抽象クラスの拡張を使用する場合、それらがコンストラクターを台無しにして物事を行うこともHttpServlet
ないと仮定するべきではありませんそれらの中で。親から呼び出さないことを選択できますが、親の引数なしのコンストラクターは常に呼び出されます。init()
init()
[...] と destroy() は finalize メソッドと同じ
いいえ、そうではありません。
サーブレットにコンストラクターとファイナライズ メソッドを使用しても問題はありません
コンストラクターとファイナライザーで例外が発生すると害が生じる可能性があります。いずれにせよ、それらを使用することはお勧めしませんが、仕様に固執しinit()
てdestroy()
準拠することをお勧めします。カスタム コンストラクターおよびデストラクターからスローされる例外の例外処理規則は仕様で定義されていないため、これらは未定義の動作/コンテナー固有になります。
彼らは呼ばれますか?
試しましたか?何が起こるのですか?
(はい:引数なしのコンストラクターが新しいスレッド インスタンスごとに呼び出され、ファイナライザーが呼び出されます... GC がそのように感じるときはいつでも。 )
コンストラクターで初期化するものが init() でオーバーライドされるか、コンストラクターがまったく呼び出されないようなものですか?
init()
コンストラクタではありません。
コンストラクターで初期化されたもの (メンバー変数など)をオーバーライドしinit()
たり、コンストラクターで実行したアクションを元に戻したり元に戻したりできる場合があります。それが役立つ理由はわかりませんが、おそらく可能です。しかし、それがあなたの言いたいことなら、彼らはお互いを打ち消すことはありません.
なぜそれをしたいのですか?
ここで私が自問する質問は、さらに次のとおりです。
- なぜここでカスタム コンストラクターが必要だと思いますか?
- なぜここでファイナライザーが必要だと思いますか? (または一般的に、実際には?)
サーブレットのライフサイクル
Servlet Lifecycleに関する Java EE 6 チュートリアルのセクションから抜粋:
- サーブレットのインスタンスが存在しない場合、Web コンテナー
- サーブレット クラスをロードします。
- サーブレット クラスのインスタンスを作成します。
- init メソッドを呼び出して、サーブレット インスタンスを初期化します。初期化については、サーブレットの作成と初期化で説明しています。
- サービス メソッドを呼び出し、リクエスト オブジェクトとレスポンス オブジェクトを渡します。サービス メソッドについては、サービス メソッドの記述で説明します。
- サーブレットを削除する必要がある場合、コンテナはサーブレットの destroy メソッドを呼び出してサーブレットをファイナライズします。詳細については、サーブレットのファイナライズを参照してください。
[...]
サーブレットの実行時に発生する例外の数に制限はありません。例外が発生すると、Web コンテナは次のメッセージを含むデフォルト ページを生成します。
サーブレット例外が発生しました
Javadoc を確認しましょうinit()
(強調は私のものです) 。
サーブレットがサービスを開始することをサーブレットに示すために、サーブレット コンテナーによって呼び出されます。
サーブレット コンテナは、サーブレットをインスタンス化した後、init メソッドを 1 回だけ呼び出します。サーブレットが要求を受け取る前に、init メソッドが正常に完了する必要があります。
init メソッドが
- ServletException をスローします
- Web サーバーによって定義された期間内に返されない
init()
そのため、 であまり消費することや、一度だけ実行する必要があることをしないように注意してください。すべてのリクエストに対して実行する必要がある場合は、リクエスト処理メソッドで実行します(例: doGet()
、doPost()
...)。
Java EE 6 チュートリアル(および Java EE 5 用) の「サーブレットの作成と初期化」も参照してください。
サーブレットがサービスを停止していることをサーブレットに示すために、サーブレット コンテナーによって呼び出されます。このメソッドは、サーブレットのサービス メソッド内のすべてのスレッドが終了した後、またはタイムアウト期間が経過した後にのみ呼び出されます。サーブレット コンテナがこのメソッドを呼び出した後、このサーブレットでサービス メソッドを再度呼び出すことはありません。
このメソッドにより、保持されているリソース (メモリ、ファイル ハンドル、スレッドなど) をクリーンアップする機会がサーブレットに与えられ、永続的な状態がメモリ内のサーブレットの現在の状態と確実に同期されます。
Java EE 6 チュートリアル(および Java EE 5 の場合)のFinalizing a Servletも参照してください(ここでは、単語の選択が不十分です...)。
歴史的なサーブレットの設計と、それをバイパスしようとする理由が BAD THING (TM) である理由の詳細については、こちらをご覧ください。
http://oreilly.com/catalog/jservlet/chapter/ch03.html#15894を参照してください。
代わりにコンストラクターを使用しないのはなぜですか? JDK 1.0 (サーブレットが最初に作成された) では、動的にロードされる Java クラス (サーブレットなど) のコンストラクターは引数を受け入れることができませんでした。そのため、新しいサーブレットにそれ自体とその環境に関する情報を提供するために、サーバーはサーブレットの init() メソッドを呼び出し、ServletConfig インターフェースを実装するオブジェクトを渡す必要がありました。また、Java では、インターフェイスでコンストラクターを宣言することはできません。これは、javax.servlet.Servlet インターフェースが、ServletConfig パラメータを受け入れるコンストラクターを宣言できないことを意味します。init() のような別のメソッドを宣言する必要があります。もちろん、サーブレットのコンストラクターを定義することも可能です。ただし、コンストラクターでは、ServletConfig オブジェクトにアクセスすることも、ServletException をスローすることもできません。
最後の文に特に注意してください。
[...] ただし、コンストラクターでは、ServletConfig オブジェクトにアクセスすることも、ServletException をスローすることもできません。
したがって、サーブレットのコンストラクターで何かを行うと、次のようになります。
- 非現実的、
- しかし、ほとんどの場合、非常に危険です!!