23

JSFでカスタムコンポーネントの開発を学んでいると、コンポーネントファミリ、コンポーネントタイプ、レンダラータイプの関係に戸惑いました。たとえば、以下に示すように、レンダラーとカスタムコンポーネントを登録しました。

faces-config.xml

<component>
    <component-type>study.faces.Div</component-type>
    <component-class>javax.faces.component.UIPanel</component-class>
</component>

<render-kit>
    <render-kit-id>HTML_BASIC</render-kit-id>
    <renderer>
        <component-family>javax.faces.Panel</component-family>
        <renderer-type>study.faces.DivRenderer</renderer-type>
        <renderer-class>com.study.ui.DivRenderer</renderer-class>
    </renderer>
</render-kit>

my.taglib.xmlまた、次のようにファイルに新しいタグを登録しました。

<tag>
    <tag-name>div</tag-name>
    <component>
        <component-type>study.faces.Div</component-type>
        <renderer-type>study.faces.DivRenderer</renderer-type>
    </component>
</tag>

この構成は非常にうまく機能します。<component-family>javax.faces.Panel</component-family>しかし、レンダラーの登録になぜその行が必要なのか理解できませんでした。ではmy.taglib.xml、コンポーネントとレンダラーが接続されており、IMHOでは、コンポーネントに適切なレンダラーを選択するだけで十分でした。追加パラメータの用途は何<component-family>ですか?

私はGoogleの調査を行い、「1つのレンダラーを使用して複数のコンポーネントをレンダリングできます。これらのコンポーネントは1つのファミリに属しています」と答えました。しかし、これらの声明は私の混乱を解消しませんでした。コンポーネントタイプ、コンポーネントファミリ、レンダラー選択戦略の関係を誰かが説明できますか?(うまくいけば、良い例があります。)

4

2 に答える 2

39

レンダラーは、期待どおりのコンポーネントタイプではなく、コンポーネントファミリによって選択されます。

JSF2.0仕様を引用しましょう:

3.1.2コンポーネントタイプ

UIComponentUIComponentのプロパティではありませんが、component-typeは、各サブクラスに関連する重要なデータであり、インスタンスがそのタイプApplicationのサブクラスの新しいインスタンスを作成できるようにします。UIComponentコンポーネントタイプの詳細については、セクション7.1.11「オブジェクトファクトリ」を参照してください。

3.1.3コンポーネントファミリ

各標準ユーザーインターフェイスコンポーネントクラスには、このコンポーネントに関連付けられているレンダラーを検索するために使用されるコンポーネントファミリの標準値があります。ジェネリックUIComponentクラスのサブクラスは通常、そのスーパークラスからこのプロパティを継承するため、スーパークラスのみを期待するレンダラーは、特殊なサブクラスを処理できます。

Application#createComponent()基本的に、JSFでは、メソッドごとにコンポーネントを作成するために、コンポーネントタイプが必須です。

UIComponent component = context.getApplication().createComponent("study.faces.Div");

これには、コンポーネントstudy.faces.Divがコンパイル時の依存関係ではないため、実行時のポリモーフィズムとプラグイン可能性の可能性を提供するという利点があります(JDBCのClass#forName()メカニズムとそのファクトリに精通している場合は、その部分をよりよく理解できます)。

各コンポーネントタイプは、1つ以上のコンポーネントで構成できるファミリに属しています。レンダラーは、コンポーネントファミリーとレンダラータイプに基づいて選択されます。RenderKit#getRenderer()

Renderer renderer = context.getRenderKit().getRenderer(component.getFamily(), component.getRendererType());

レンダラーは、コンポーネントタイプとレンダラータイプに基づいて選択されません。これにより、コンポーネントファミリに属する​​複数のコンポーネントタイプでレンダラーを再利用できます。そうしないと、コンポーネントが同じレンダラーを共有できる場合でも、コンポーネントごとに1つのレンダラーを登録する必要があります。

次のfaces-config.xmlエントリ

<component>
    <component-type>study.faces.Div</component-type>
    <component-class>javax.faces.component.UIPanel</component-class>
</component>

Application指定されたコンポーネントタイプのコンポーネントを作成する場合は常に、指定されたコンポーネントクラスのインスタンスを作成する必要があることをJSFに通知します。コンポーネントファミリは、ですでに暗黙的に認識されているため、ここでは指定されていませんcomponent.getFamily()

そして次のfaces-config.xmlエントリ

<render-kit>
    <renderer>
        <component-family>javax.faces.Panel</component-family>
        <renderer-type>study.faces.DivRenderer</renderer-type>
        <renderer-class>com.study.ui.DivRenderer</renderer-class>
    </renderer>
</render-kit>

RenderKit指定されたコンポーネントファミリおよびレンダラータイプのレンダラーが要求されるたびに、が指定されたレンダラークラスのインスタンスを返す必要があることをJSFに通知します。

次の.taglib.xmlエントリ

<tag>
    <tag-name>div</tag-name>
    <component>
        <component-type>study.faces.Div</component-type>
        <renderer-type>study.faces.DivRenderer</renderer-type>
    </component>
</tag>

JSF(まあ、Facelets)に、指定されたタグがビュールート(クラスが定義されている)に指定されたコンポーネントタイプのコンポーネントを作成する必要がfaces-config.xmlあり、そのレンダラータイプが指定されたレンダラータイプに設定される必要があることを通知します。コンポーネントタイプはレンダラーの選択には使用されず、代わりにビュールートにコンポーネントを作成するために使用されることに注意してください。また、レンダラータイプのエントリはオプションであることに注意してください。それ以外の場合は、コンポーネント独自の事前定義されたレンダラータイプが使用されます。これにより、既存のコンポーネントタイプを別のレンダラータイプで再利用できます。

于 2011-11-10T12:10:12.460 に答える
3

javadocによるとgetFamily()

このコンポーネントが属するコンポーネントファミリの識別子を返します。この識別子は、 rendererTypeプロパティの値と組み合わせて、 このコンポーネントインスタンスに適切な レンダラーを選択するために使用できます。

メンテナの論理的根拠はJSF仕様でカバーされています:

コンポーネントファミリ

各標準ユーザーインターフェイスコンポーネントクラスには、このコンポーネントに関連付けられているレンダラーを検索するために使用されるコンポーネントファミリの標準値があります。一般的なUIComponentクラスのサブクラスは、通常、そのスーパークラスからこのプロパティを継承するため、スーパークラスのみを期待するレンダラーは、特殊なサブクラスを処理できます。

これは、Javaクラス型以外の追加の型チェック機能を提供するものと解釈します(サブクラスは常にサブクラスになるため)。これが実際にどれほど役立つかはわかりません。

于 2011-11-10T11:57:23.520 に答える