1.进入页面后如何根据@ManagedBean找到对应的后台Java类
(1).装载类@ManagedBean的描述信息
启动服务器的时候,FacesConfig的load方法里将配置中的及扫描OperaMasks源码包中的classes目录下的所有类文件,将包含@ManagedBean的类的描述信息类ManagedBeanConfig统一装到ManagedBeanContainer中。这个类中包含了所有的后台Bean的信息,如类名、类的范围。而ManagedBeanContainer是保存于ApplicationAssociate中的,然后ApplicationAssociate是保存于Application中的,所以该ManagedBeanContainer在应用生命周期都是可以访问得到的。
(2).访问并构建@ManagedBean
在第一和第六阶段,将会进行ModelBindingFactory的applyModelBinding()方法将model bindings到具体的视图view上。里面的getBeans方法理所当然后的调用了由第一点所说的ManagedBeanContainer中查找相应的ManagedBeanConfig,并通过反射的方式构造该Bean,既然无法预知要处理的Bean的构造函数是啥,所以框架要求必须要有无参构造函数,默认不传递任何参数,ManagedBean若不设置无参构造函数,则运行页面时报错。
查找过程涉及到映射规则的匹配,即涉及到operamasks.xml中配置的ManagedBean映射规则。
在DefaultManagedBeanContainer的storeBean的过程中,将ManagedBean存储到与ManagedBeanConfig对应的scope中去,如Request或者是Session又或者是Application范围。
在任何的后台Bean寻找过程都可以通过这个过程来查找,从另一个角度讲,在业务代码中要获取某一个后台Bean都是可以做到的,只要传入相应的EL表达式,由OperaMasks引擎来做初始化工作,并返回相应的Bean实例。可以看到FacesUtils.getBean(String name)方法就是使用这种获取后台Bean的方式。
至此,我们完成了ManagedBean的创建和存储,并提供了查找方式,后续的注解提供了实例。
2.@BeforeRender
@BeforeRender太常用了,很多时候我们都需要在渲染页面前进行一些值的初始化。
上面第1步的操作已经将ManagedBean准备好,在getBeans()后获取正确的Bean,接下来,我们首先要知道的是如何扫描其他的注解信息。
已经可以看到BindingBuilder的scan方法了。在BindingBuilder的scan方法里,主要是对配置于comp-core/src/main/resources/META-INF/bean_processors.cfg及/mnt/project/workspace/om/workspace/operamasks-core/src/main/resources/org/operamasks/faces/binding/impl/processor/bean/bean_processors.cfg中配置的Class进行扫描并与bean中的注解进行对比,若存在该与配置文件对应的注解,则找到该类,如BeforeRender对应的是BeforeRenderProcessor.java,其build方法将BeforeRender解释成一个PhaseListenerBinding对象,后添加到ModelBinderImpl.java中的bindings属性中,如果是@BeforeRender,则添加到view的事件监听队列中,如果是@Action呢,好的,我们来看看原理吧,或者是Bind呢,都可以找得到。
好了,前面所说的只是在构建binding所做的一切。这些都是只是负责将注解解析成Binding,只是记录了注解所要记录的信息。
后面的事情就留给applyGlobal和applyModel来解决吧,在ModelBindingFactory的applyModelBinding方法中。
在这里,每一个已经绑定的Binding进行各进的applyGlobal及applyModel方法的调用,IoVC至此将完成。
来,我们来分析一下@BeforeRender对应的PhaseListenerBinding在applyGlobal及applyModel方法里做了什么!在applyGlobal方法中,view.setBeforePhaseListener(adapter)往视图里写了监听器。好了,当视图渲染前的事件队列调用时,则可调到此方法。PhaseListenerBinding没有覆盖Binding中的apply方法,父类Binding在该方法中没有做任何事情。同理@AfterRender及@BeforePhase及@AfterPhase都是同样的实现方式。
3.@Action
(1).通过2的方式@Action对应的是ActionProcessor及ActionBinding,同理ActionProcessor在build()方法中创建ActionBinding对象。
(2).首先调用ActionBinding的applyGlobal,由于其没有覆盖applyGlobal方法,父类Binding不做任何事情;
(3).在ActionBinding的apply方法中则将@Action对应的Component进行attachEvent绑定事件,那么在ViewRoot.broatcast()事件响应的时候在事件队列寻找事件源的时候则可以找到并进行相应方法的调用。并设置button控件的相应的状态信息,达到统一控制button的效果。
太神奇了。
4.@Bind
(1).通过2的方式@Bind对应的是BindProcessor及ValueBinding
(2).首先看applyGlobal
(3).在其apply方法中,调用到EL来解析属性值,并将值填入到comp中。当然了,这里得细看,因为Binding只是将EL表达式整合到一起,它有多种类型的绑定,到真正求值的时候如getValue的值才会调用到。
5.@Init
6.@Inject
7.@ManagedProperty
这个需要注意,在注解扫描时做了一些事情,ManagedBeanConfig
备注:
引自:http://wiki.operamasks.org/pages/viewpage.action?pageId=7635152
@ManagedProperty注入发生在ManagedBean刚创建时,这个动作是在进入JSF生命周期之前完成的(也就是在restore view阶段之前,就已经注入了)。
@Inject发生在IoVC绑定过程中,在首次请求时,IoVC发生在Render Response 阶段,因此在Restore View 的所有生命周期Listener中会得到空,在@BeforeRender 方法中可正确获取。在postback时,IoVC在Restore View 与Render Response 阶段各发生一次,在绑定过程中有可能会更新@Inject所绑 定的内容(详见下一段)。如果Bean的Scope是session或者application,由于在首次调用时已经注入了,因此在aom:Postback 时一般不会为空,但在Restore View 之前的Listener中会获得旧值(如果程序需要更新注入值的话);如果 Bean的Scope是none或者request,则在Restore View 之前的Listener中会获得空值。
那么AOM是如何判断@Inject注入的值在每个请求生命周期中是否更新(重新注入)呢?规则如下:
BindingBuilder故名思异,用于构建Binding实例。
1.哪些东西需要构建Binding实例呢?
2.如何构建呢?
答:
1.所有与iovc相关的类都需要进行构建Binding实例
这些相Binding实例对对应的处理类记录在org/operamasks/faces/binding/impl/processor/bean/bean_processors.cfg文件中。每一个processor类都对应着一个注解,给BindingBuilder进行扫描时对比,并调用相关的processor类。组件体系开发人员可以自己指定自己的iovc实现类,记录在文件META-INF/bean_processors.cfg里,但前提是非常的熟悉aom的iovc引擎,否则很难写出与之相关的iovc实现。
2.BindingBuilder的扫描策略
public void build(Class<?> targetClass);方法里进行了递归调用,先scan当前Class,然后再scan父interface及父类。 若有打上iovc中的annotation的话,则在processor类里调用process方法,其中构建相应的Binding实例,添加到BindingBuilder的binding列表中。
1.在哪里把@Init标注的方法写到调用列表中
2.在哪里进行@Init方法的调用
指定了标签的value属性后,不会再调用@Init的方法,@Init依赖于IoVC
参考文献:
[1] 绑定与注入问题:http://wiki.operamasks.org/pages/viewpage.action?pageId=7635152
[2] AOM JSF引擎实现概述文档:http://www.operamasks.org/forum/thread-2621-1-4.html