LiteBean,脱胎于JSF规范中的 Managed Bean,在 AOM 2.0中,对 Managed Bean 做了大量的扩充,最终演化成了目前的 LiteBean。LiteBean 是 AOM 中非常重要的一个概念,它即是展现层与业务层之间的粘接器,同时也是 AOM 与其它成熟编程模型的粘接器,如 Spring、EJB 3 等。
事实上,在我们前面几篇文章中,已经大量涉及到 LiteBean 相关内容,但我们从来没有系统化的介绍过 LiteBean,本文,将对各位读者整体的介绍一下 LiteBean 相关内容。
另外需要注意的是:@ManagedBean 的 annotation 将逐渐被 @LiteBean 代替,但为了保持兼容性,本文将继续延用 @ManagedBean 这个 annotation。
LiteBean的声明在AOM中是非常简单的一件事情,只需要一个 @ManagedBean 的 annotation 声明即可。一个比较完整的LiteBean声明如下:
@ManagedBean(name="LiteBean", scope=ManagedBeanScope.NONE, description="The description", displayName="your_display_name")
public class LiteBean {
}
其中,如果不指定name,那么,默认以类名称(不含包名)作为name,scope的默认值为none,description及displayName基本上都可以忽略。
所以,一个更简单的LiteBean的声明是:
@ManagedBean
public class LiteBean {
}
由于LiteBean是被容器自动创建的,因此,很自然的,LiteBean必须要有个无参数的构造函数。有的同学要问了:“有时候通过无参数的构造器进行 LiteBean 的创建方式不能够完全满足我的要求, 因为在某些场景下,我需要知道一些上下文,才能够正确的创建并初始化一个LiteBean,这种情况如何解决?” 这种情况下,你可以通过Factory模式来创建LiteBean,如下所示:
@ManagedBean(scope=ManagedBeanScope.APPLICATION)
public class UserFactory {
@Factory(name="user", scope=ManagedBeanScope.SESSION)
public User createUser() {
return new User();
}
}
请注意,这个Factory本身也必须要是个LiteBean。
LiteBean被声明以后,就能够被EL表达式所引用了,但如果你要访问LiteBean的属性,那么,你还要为该属性准备 getter/setter 方法。笔者并不认为 getter/setter 方法存在什么问题,但事实上,某些场景下,getter/setter 方法过多,确实会影响到开发者的注意力,因此,AOM中又引入了一个 @ManagedProperty 的 annotation,如果在一个属性上进行@ManagedProperty的标注,那么,这个属性就成为“Managed Property”,并可以被EL表达式引用,如:
@ManagedBean
public class LiteBean {
@ManagedProperty
private String name;
}
此时,你可以通过#{LiteBean.name}引用这个变量。但 @ManagedProperty 的作用并不仅限于此,你还可以在该声明中指定一个EL表达式,该EL表达式的值,将作为该属性的初始化值,如:
@ManagedBean
public class LiteBean {
@ManagedProperty("#{OtherLiteBean.someProperty}")
private String name;
}
基本上,我们从来不需要再维护faces-config.xml,但我们也不排斥通过 faces-config.xml 来进行 ManagedBean/ManagedProperty的声明。
此外需要提醒读者注意的是,如果在@ManagedProperty中通过EL表达式引入别的 LiteBean,需要注意 LiteBean的生命周期,下面就让我们来介绍一下什么是 LiteBean的生命周期。
写过jsp程序的同学都了解在jsp页面中,有几个默认隐含对象,如:request、session、application等,我们经常会把一些信息存放到这些对象域中,其中又以 session 对象使用的最为频繁。同样的,一个 LiteBean 被创建以后,也会被放到这些不同的生命周期域里,分别是:
request:指从请求开始至请求结束期间。
session:指用户的会话过程期间。
application:指应用的整个生命周期。
简单来说:当一个应用启动时,AOM会扫描该应用中的所有类,从中找出所有的 LiteBean(会记住它的name及其对应的具体Java类),当在需要引用某一个LiteBean时,它会从 request、session、application域中依次查找是否已经存在该LiteBean,如果不存在,那就创建它并将其放入到指定的生命周期域里。
此外,LiteBean还有一个名称为none的生命周期范围,意思就是说:此LiteBean每次都创建新的实例,用完就丢掉。
由此,我们也明白了另外一个逻辑:如果一个 LiteBean 引用了另外一个 LiteBean,那么,被引用的LiteBean的生命周期,一定要长于或等于引用的这个LiteBean。
Table1.合法的LiteBean引用
引用的LiteBean的生命周期 |
被引用的LiteBean的生命周期 |
none |
none |
application |
none, application |
session |
none, application, session |
reqeust |
none, application, session, request |
LiteBean可以被页面中的EL表达式所使用,但基于 IoVC 思想,我们是竭力避免在页面中出现 EL 表达式的,那么这就引来一个问题:一个页面,到底是如何跟某个或者某几个LiteBean关联起来的呢?
你可以认为是通过配置文件关联起来的,你也可以认为是基于“约定优于配置”这一原则而约定成俗的。而实际情况是: 你即可以通过配置文件指定,也可以采用约定规则,包括这种约定能力的自身也是配置出来 的。
这个配置文件就是在 AOM 2.0中引入的 operamasks.xml,位于web应用的 WEB-INF目录下。事实上,这个文件默认都会包含如下内容,并且,我们也强烈推荐你加上此段内容:
<operamasks-config xmlns="http://www.operamasks.org/IoVC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.operamasks.org/IoVC http://www.operamasks.org/schema/operamasks.xsd ">
<view-mapping>
<url-pattern>*</url-pattern>
<model-bean>#{~View}Bean</model-bean>
</view-mapping>
</operamasks-config>
上述配置,实际上就是配置了一种约定能力,解释如下:如果页面的文件名是 abc.xhtml(扩展名不定,也可以是abc.jsp),那么,所对应的 LiteBean 的名称是 AbcBean。甚至你的文件名称可以是a-b-c.xhtml,对应的 LiteBean的名称依然是 AbcBean(请注意是LiteBean的name,而不是 java类的名称)。如果你希望LiteBean name的首字母小写,那就将配置文件改成:
<model-bean>#{~view}Bean</model-bean>
那么,abc.xhtml,对应的LiteBean就是:abcBean。
如果应用变得复杂,文件要分目录存放,那么,建议你再做如下配置:
<view-mapping>
<url-pattern>/gl/*</url-pattern>
<model-bean>gl.#{@View}Bean</model-bean>
</view-mapping>
上述配置意思就是:凡位于gl目录下的页面,其对应的 LiteBean的名称就有前缀 gl,譬如 /gl/abc.xhtml 对应的 LiteBean 的 name 就是:gl.AbcBean;gl/test/def.xhtml 对应的 LiteBean 的 name 则是:gl.test.DefBean。
当然,如果你要单独指定某个页面所对应的LiteBean,那就这样:
<view-mapping>
<url-pattern>/user/login.xhtml</url-pattern>
<model-bean>LoginBean</model-bean>
<model-bean>RegisterBean</model-bean>
<model-bean>UserListBean</model-bean>
</view-mapping>
在上述情况下,login.xhtml会对应LoginBean、RegisterBean、UserListBean这三个LiteBean。
事实上,如果你用 Apusic Studio 来进行开发工作的话,这个文件(operamasks.xml)你根本不需要关心,由 Apusic Studio自动帮你维护。
再次强调:针对页面和对应的 LiteBean ,我们强烈建议您采用“约定优于配置”这一原则,而在 AOM 中,这种约定的能力也是配置出来的。
时至今日,Inversion of Control,Dependency Injection,等概念已经耳熟能详;Spring等IoC容器也大行其道;甚至于很多同学并没有真正理解到底什么是IoC以及它带给我们的意义, 但一个个的Spring用得倍熟。究其原因,是因为 Spring 为我们提供了许多便利,尤其是对象的创建与销毁。AOM同样如此,你所需要的任何资源,只需要通过一个 @Inject 即可注入。在 AOM 中,你可以注入以下资源:
java.util.logging.Logger
javax.faces.context.FacesContext
javax.faces.context.ExternalContext
javax.faces.application.Application
javax.faces.application.NavigationHandler
javax.el.ExpressionFactory
org.operamasks.faces.event.EventBroadcaster
org.apache.commons.logging.Log
举个简单的例子,如果你要使用 java.util.logging.Logger对象,那么,你只需要:
@Inject
private Logger logger
AOM会根据对象类型自然判断出你需要注入的资源是什么。上例中,由于Logger是 java.util.longg.Logger,因此,AOM会自动初始化 logger对象,然后你就可以拿着 logger 对象直接用了。
此外,你还可以在@Inject中指定EL表达式,AOM会对该EL表达式求值,并将结果赋值给该属性,如:
@ManagedBean(name="testBean", scope=ManagedBeanScope.SESSION)
public class TestBean {
@Inject("#{LiteBean.name}")
private String name;
}
如果你希望上述属性能够被EL表达式所访问,那么,你就再加一个 @Accessible 的声明:
@ManagedBean
public class TestBean {
@Inject("#{LiteBean.name}")
@Accessible
private String name;
}
这样,别人就可以通过#{TestBean.name}访问该属性了。
同时,AOM也支持JavaEE 5.0中规定的跟资源注入相关的 Annotation,如:
@Resource
@Resources
@EJB
@EJBs
@WebServiceRef
@WebServiceRefs
@PersistenceContext
@PersistenceContexts
@PersistenceUnit
@PersistenceUnits
假设我要注入一个数据源,那么,你可以这样:
@Resource(mappedName="jdbc/MyDataSource")
DataSource ds;
有同学要问了:这种资源注入的方式很好用啊,我能否将其扩展,让我的开发团队使用这种便捷的方式来注入自己的对象呢?譬如说, 我现在有一些自己的对象,这些对象都有自己的名字,我能否很方便的通过名字来注入相应的对象呢?
自然没问题,AOM是开放的,其架构的灵活性,也足以支撑这种扩展,譬如,你可以实现一个自己的ELResolver,然后通过 ApplicationListener注册到AOM。本文中,笔者不想介绍这么复杂的内容,只是通过一种简单的模式来解决此问题,示例性代码如下:
@ManagedBean
public class MyBeanFactory {
public Object get(String name) {
if("someKey".equals(name)) {
return new MyBean1();
}
else if ("otherKey".equals(name)) {
return new MyBean2();
}
return new MyBean3();
}
}
如果要注入相关资源,可以这样:
@Inject("#{MyBeanFactory.get('someKey')}")
private MyBean1 bean1;
@Inject("#{MyBeanFactory.get('otherKey')}")
private MyBean2 bean2;
LiteBean是AOM中非常重要的一个概念,它即是展现层与业务层的粘接器,同时也是 AOM 与其它编程模型(如Spring、EJB 3等)的粘接器。在下文中,我们将介绍 AOM 是怎样与 Spring 紧密集成的。
相关推荐
使用QTP的automation object model,可以对QTP进行自动化编程,从而自动对QTP进行选项设置、自动运行测试(或组件),而无需使用QTP界面手工进行这些操作。 如果要重复多次的完成同一项工作任务,或重复多次运行同一...
什么是 AoM? AoM 是 Argentum Online 的改装平台。 阅读有关 AoM 的更多信息版权所有 (c) 2015 AoM Powered 执照AoM 在下获得 ,请参阅LICENSE文件了解详细信息。贡献AoM 是 100% 免费和开源的。 我们鼓励并支持...
在这个过程中,`aom-v1.0.0.errata.1.tar.gz`是一个重要的组件,它是Google开放媒体联盟(Alliance for Open Media, AOMedia)的AV1编码器开源实现——AOMedia Video 1(AV1)的一个版本。AV1是一种高效、开放标准的...
各位AOM的爱好者,AOM目前采用的默认EXT皮肤很漂亮,但是从1.0用到2.0再用到2.3,想必各位的项目都已经成熟稳定了,这时候很多人想锦上添花,让自己的项目更加出众一些,那就要在外观上做一些美化了。 遗憾的是,...
标题 "aom-v1.0.0.errata.1.tar.gz" 指的是一个名为 "aom" 的开源项目,其版本为1.0.0的错误修复更新(errata)第一版,并以tar.gz格式打包。这个压缩包包含了项目的一些核心文件和文档,表明这可能是用于开发或维护...
标题"AOM初体验(一)"以及描述中提到的工程打包下载,暗示了这是一个关于应用开发和集成环境的讨论,特别是涉及到AOM(可能是Apusic Application Object Model,一种中间件平台)的使用。标签"源码"和"工具"进一步...
AOM(Academy of Motion Picture Arts and Sciences)是一个与电影技术相关的组织,而在此上下文中,它似乎指的是一个特定的Java项目或库。"AOM java原代码下载"的标题表明我们正在讨论的是该组织的Java源代码,可能...
AOM 通过engine.vbs 启动UFT。
标题 "aom-v1.0.0.errata.1.zip" 指示这是一个与开源视频编码库AV1相关的更新或修正文件。"errata"通常用于标识软件发布中的错误或修正,这意味着这个压缩包可能包含了针对aomedia(aom)v1.0.0版本的一些修复或改进...
标题"AOM相关.rar"指的是与AOMedia(简称AOM)相关的资料集合,这通常涉及到音视频编码技术,特别是AV1编码标准。AOMedia是一个开放的非营利组织,致力于开发下一代开源、免专利费的媒体编码技术,旨在提供高质量的...
标题 "aom.zip_3344aom_aom.avcom_av1_h264_zip" 暗示了这是一个与视频编码相关的压缩文件,其中包含了AV1编码器的源代码,可能还有与H264编码的对比或转换相关的资料。描述 "av1 codec source open c++" 明确指出这...
本文将深入探讨“第二波又来了:AOM3.2之8款皮肤分享(for extjs3.31)”这个主题,这是一次针对AOM(Opera Masks)3.2版本发布的皮肤更新,特别设计以兼容ExtJS 3.3.1框架。 AOM,全称Antelope on the Moon,是一个...
【X-AOM权识区块链新经济 - 泛AI时代投资多元的解决方案】 X-AOM权识区块链新经济项目旨在利用区块链技术,特别是在泛人工智能(AI)时代,为投资者提供多元化投资的策略。该项目的核心目标是建立一个全球化的平台...
海洋沉积物甲烷厌氧氧化(AOM)作用是一个涉及甲烷和硫酸盐的生物地球化学过程,甲烷作为一种温室气体,在海洋沉积物中通过与硫酸盐还原菌作用被转化为二氧化碳或碳酸盐,同时硫酸盐作为电子受体被还原为硫化物。...
管理学院风格的 TeX 模板这是用于向管理学会 (AOM) 会议提交论文的 TeX 模板。 它遵循详述的大多数样式指南,但目前尚不完整(请参阅当前的)。 欢迎更新和修复。 它目前采用 Times New Roman 格式,边距为一英寸,...
AOM金蝶控件开发指南,入门,供大家学习
"AOM中IE、Firefox兼容Enter代替Tab的Javascript"这个主题关注的是如何在不同的浏览器环境中,尤其是IE和Firefox中,使用JavaScript实现按下回车键(Enter)时模拟Tab键的效果,以实现元素间的焦点切换。 首先,我们...