[解決済み】JSFがゲッターを複数回呼び出す理由
質問
例えば、次のようなoutputTextコンポーネントを指定するとします。
<h:outputText value="#{ManagedBean.someProperty}"/>
のゲッターの時にログメッセージを出力すると
someProperty
が呼び出され、ページを読み込むと、ゲッターが1回のリクエストにつき2回以上呼び出されていることに気づくのは簡単です (私の場合は2回か3回でした)。
DEBUG 2010-01-18 23:31:40,104 (ManagedBean.java:13) - Getting some property
DEBUG 2010-01-18 23:31:40,104 (ManagedBean.java:13) - Getting some property
の値が
someProperty
を計算するのが面倒な場合、問題になる可能性があります。
ちょっとググってみたところ、これは既知の問題だと思いました。回避策としては、すでに計算されているかどうかのチェックを入れることでした。
private String someProperty;
public String getSomeProperty() {
if (this.someProperty == null) {
this.someProperty = this.calculatePropertyValue();
}
return this.someProperty;
}
この方法の主な問題点は、定型的なコードが多くなること、そして言うまでもなく、必要のないプライベート変数が増えることです。
このアプローチに代わるものは何でしょうか?不要なコードをあまり書かずに実現する方法はないでしょうか?JSFがこのような振る舞いをしないようにする方法はあるのでしょうか?
ご意見ありがとうございました。
解決方法は?
これは、遅延表現の性質に起因するものです
#{}
(ただし、レガシーな標準表現である
${}
は、JSPの代わりにFaceletsを使用した場合でも全く同じ動作をします)。遅延式は
すぐに
として作成されます。
ValueExpression
を呼び出すと、その式の背後にあるゲッターメソッドが毎回実行されます。
ValueExpression#getValue()
.
これは通常、コンポーネントが入力コンポーネントか出力コンポーネントかによって、JSFのリクエスト・レスポンスサイクルごとに1回または2回呼び出されます(
ここで学ぶ
). しかし、JSFコンポーネントを繰り返し使用する場合、このカウントは(はるかに)高くなることがあります (
<h:dataTable>
と
<ui:repeat>
のようなブーリアン表現があちこちにあります)。
rendered
属性があります。JSF(具体的にはEL)はEL式の評価結果を全くキャッシュしないので
かもしれない
は、呼び出しごとに異なる値を返します (たとえば、現在反復処理されているデータテーブル行に依存している場合など)。
EL式の評価とゲッターメソッドの起動は非常に安価な処理ですので、一般的には全く気にする必要はありません。しかし、何らかの理由でゲッターメソッド内で高価なDB/ビジネスロジックを実行する場合には、話は変わってきます。これでは毎回再実行されてしまう!
JSFのバッキングビーンにおけるゲッターメソッドは、もっぱら以下のように設計されるべきです。
返す
のように、すでに準備されたプロパティとそれ以外のものはありません。
Javabeansの仕様
. 高価なDB/ビジネスロジックは一切行うべきではありません。そのために,ビーンの
@PostConstruct
や(アクション)リスナーメソッドを使用する必要があります。これらは、以下のように実行されます。
一度だけ
リクエストベースのJSFのライフサイクルのある時点で、それはまさにあなたが望むものです。
以下は、さまざまな 正しい プロパティをプリセット/ロードする方法。
public class Bean {
private SomeObject someProperty;
@PostConstruct
public void init() {
// In @PostConstruct (will be invoked immediately after construction and dependency/property injection).
someProperty = loadSomeProperty();
}
public void onload() {
// Or in GET action method (e.g. <f:viewAction action>).
someProperty = loadSomeProperty();
}
public void preRender(ComponentSystemEvent event) {
// Or in some SystemEvent method (e.g. <f:event type="preRenderView">).
someProperty = loadSomeProperty();
}
public void change(ValueChangeEvent event) {
// Or in some FacesEvent method (e.g. <h:inputXxx valueChangeListener>).
someProperty = loadSomeProperty();
}
public void ajaxListener(AjaxBehaviorEvent event) {
// Or in some BehaviorEvent method (e.g. <f:ajax listener>).
someProperty = loadSomeProperty();
}
public void actionListener(ActionEvent event) {
// Or in some ActionEvent method (e.g. <h:commandXxx actionListener>).
someProperty = loadSomeProperty();
}
public String submit() {
// Or in POST action method (e.g. <h:commandXxx action>).
someProperty = loadSomeProperty();
return "outcome";
}
public SomeObject getSomeProperty() {
// Just keep getter untouched. It isn't intented to do business logic!
return someProperty;
}
}
注意点としては ではなく なぜなら、CDI のようなプロキシを使用する Bean 管理フレームワークを使用している場合、 複数回起動される可能性があるからです。
もし他に方法がないのであれば、ゲッターメソッドの中にレイジーローディングを導入してください。つまり、もしプロパティが
null
を読み込んでプロパティに代入し、そうでなければそれを返します。
public SomeObject getSomeProperty() {
// If there are really no other ways, introduce lazy loading.
if (someProperty == null) {
someProperty = loadSomeProperty();
}
return someProperty;
}
こうすることで、高価なDB/ビジネスロジックが、ゲッター呼び出しのたびに不必要に実行されることがなくなります。
こちらもご覧ください。
関連
-
[解決済み] apacheサーバーがMaxClientsの設定に達したので、MaxClientsの設定を上げることを検討してください。
-
[解決済み] B "の印刷が "#"の印刷より劇的に遅いのはなぜですか?
-
[解決済み] Python 3で「1000000000000000 in range(1000000000000001)」はなぜ速いのですか?
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] なぜゲッターとセッター/アクセッサーを使うのですか?
-
[解決済み] 0.1fを0にすると、なぜ10倍もパフォーマンスが落ちるのですか?
-
[解決済み】JSF、Servlet、JSPの違いは何ですか?
-
[解決済み】PyPyが6.3倍速いなら、CPythonよりPyPyを使うべきじゃないのか?
-
[解決済み] 3Dゲームってなんであんなに効率的なの?[クローズド]
-
[解決済み] 与えられた数の除数の数を計算するアルゴリズム
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 実行時間(高速化)の計算方法
-
[解決済み] HadoopのMapreduceジョブでJVMを再利用する。
-
[解決済み] πの値を最も早く求める方法は何ですか?
-
[解決済み】再帰はループより速いことがあるのか?
-
[解決済み】-depth 1でcloneを浅くし、コミットを作成し、再び更新をpullするのは安全ですか?
-
[解決済み】Goはどうしてそんなに早くコンパイルできるのですか?
-
[解決済み】GHCコアの読み込み
-
[解決済み] 3Dゲームってなんであんなに効率的なの?[クローズド]
-
[解決済み] gccのffast-mathは実際に何をするのですか?
-
[解決済み] SSLはどれくらいのオーバーヘッドを発生させるのですか?