Ответ 1
Средство рендеринга выбирается семейством компонентов, а не типом компонента, как вы ожидаете.
Пусть приведена спецификация JSF 2.0:
3.1.2 Тип компонента
Не являясь свойством UIComponent, компонентный тип является важной частью данных, относящихся к каждому подклассу
UIComponent
, который позволяет экземпляруApplication
создавать новые экземпляры подклассовUIComponent
с этим типом. Подробнее о компонентном типе см. Раздел 7.1.11 "Объектные объекты".3.1.3 Семейство компонентов
Каждый класс компонентов стандартного пользовательского интерфейса имеет стандартное значение для семейства компонентов, которое используется для поиска рендеринга, связанного с этим компонентом. Подклассы общего класса
UIComponent
, как правило, наследуют это свойство из своего суперкласса, так что рендереры, которые только ожидают, что суперкласс будет по-прежнему обрабатывать специализированные подклассы.
В принципе, тип компонента является обязательным для JSF для создания компонента методом Application#createComponent()
.
UIComponent component = context.getApplication().createComponent("study.faces.Div");
Это имеет то преимущество, что компонент study.faces.Div
не является зависимой от времени компиляции и, следовательно, предлагает возможности полиморфизма во время выполнения и возможности подключения (если вы знакомы с механизмом JDBC Class#forName()
и его заводы, тогда вы поймете эту часть лучше).
Каждый тип компонента принадлежит к семейству, которое может состоять из одного или нескольких компонентов. Средство рендеринга выбирается на основе семейства компонентов и типа визуализатора с помощью RenderKit#getRenderer()
Renderer renderer = context.getRenderKit().getRenderer(component.getFamily(), component.getRendererType());
Средство рендеринга не, выбранное на основе типа компонента и типа визуализатора. Это позволяет повторно использовать средство визуализации для нескольких типов компонентов, принадлежащих к семейству компонентов. В противном случае вам нужно будет зарегистрировать один рендерер для каждого отдельного компонента, даже если компоненты могут совместно использовать один и тот же рендерер.
Следующая запись faces-config.xml
<component>
<component-type>study.faces.Div</component-type>
<component-class>javax.faces.component.UIPanel</component-class>
</component>
сообщает JSF, что Application
должен создавать экземпляр данного класса компонента всякий раз, когда должен быть создан компонент данного типа компонента. Семейство компонентов здесь не указано, потому что это уже неявно известно 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>
сообщает JSF, что RenderKit
должен возвращать экземпляр данного класса рендеринга всякий раз, когда запрашивается средство визуализации данного семейства компонентов и типа визуализатора.
Следующая запись .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
) и что его тип визуализатора должен быть установлен на данный рендерер тип. Обратите внимание, что тип компонента не используется для выбора средства визуализации, вместо этого он используется для создания компонента в корне представления. Также обратите внимание, что запись типа визуализатора является необязательной. В противном случае будет использоваться собственный тип предопределенного визуализатора компонента. Это позволяет повторно использовать существующие типы компонентов с другим видом визуализатора.