组件系列,组件类型和渲染器类型之间的关系是什么?
当我在JSF中学习自定义组件开发时,我对组件系列,组件类型和渲染器类型之间的关系感到困惑。 例如,我注册了一个渲染器和一个自定义组件,如下所示。
faces-config.xml
:
study.faces.Div javax.faces.component.UIPanel HTML_BASIC javax.faces.Panel study.faces.DivRenderer com.study.ui.DivRenderer
我还在my.taglib.xml
文件中注册了一个新标记,如下所示:
div study.faces.Div study.faces.DivRenderer
这种配置非常有效。 但是,我不明白为什么在渲染器注册时需要行javax.faces.Panel
。 在my.taglib.xml
,组件和渲染器已连接,恕我直言,它应该足以为组件选择合适的渲染器。 附加参数的用途是什么?
我做了谷歌研究,我得到的所有答案都说“一个渲染器可以用来渲染多个组件。这些组件属于一个系列”。 但这些陈述并没有清楚我的困惑。 有人可以解释组件类型,组件系列和渲染器选择策略之间的关系吗? (希望有一个很好的例子。)
渲染器由组件系列选择,而不是您所期望的组件类型。
让我们引用JSF 2.0规范 :
3.1.2组件类型
虽然不是UIComponent的属性,但component-type是与每个
UIComponent
子类相关的重要数据,它允许Application
实例使用该类型创建UIComponent
子类的新实例。 有关组件类型的更多信息,请参见第7.1.11节“对象工厂”。3.1.3组件系列
每个标准用户界面组件类都具有组件系列的标准值,该值用于查找与此组件关联的渲染器。 通用
UIComponent
类的子类通常会从其超类inheritance此属性,因此只需要超类的渲染器仍然可以处理专门的子类。
基本上,组件类型对于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
条目
study.faces.Div javax.faces.component.UIPanel
告诉JSF,只要要创建给定组件类型的组件, Application
应该创建给定组件类的实例。 在那里没有指定组件系列,因为component.getFamily()
已经隐含地知道它。
以及faces-config.xml
条目
javax.faces.Panel study.faces.DivRenderer com.study.ui.DivRenderer
告诉JSF,只要请求了给定组件系列和渲染器类型的渲染器, RenderKit
应该返回给定渲染器类的实例。
以下.taglib.xml
条目
div study.faces.Div study.faces.DivRenderer
告诉JSF(好吧,Facelets),给定的标签应该在视图根目录中创建给定组件类型的组件(其类已在faces-config.xml
),并且其渲染器类型应设置为给定的渲染器类型。 请注意,组件类型不用于选择渲染器,而是用于在视图根中创建组件。 另请注意,渲染器类型条目是可选的。 否则将使用组件自己的预定义渲染器类型。 这允许使用不同的渲染器类型重用现有的组件类型。
javadoc说getFamily()
:
返回此组件所属的组件系列的标识符。 此标识符与rendererType属性的值一起可用于为此组件实例选择适当的呈现器 。
维护者的基本原理包含在JSF规范中 :
组件系列
每个标准用户界面组件类都具有组件系列的标准值,该值用于查找与此组件关联的渲染器。 通用UIComponent类的子类通常会从其超类inheritance此属性,因此只需要超类的渲染器仍然可以处理专门的子类。
我将此解释为为Java类类型之外的其他类型检查提供了一些能力(因为子类将始终是子类。)我不确定这是多么有用。