三、应用案例分析
在本文的后面,我们将使用一个"传感器网络监控系统"示例来说明JBoss POJO缓存在提供即时的良好粒度的状态复制和自动保存状态对象关系方面的能力。
(一) 问题描述
沿着一条高速铁路有一些不同的站点,这里有几千个传感器需要被监视和监控。这些仪器的一些示例包括温度,风和雨传感器-它们对于高速铁路的正常运转至关重要。如果一个特别的传感器正在失灵,那么在监督的系统中的管理器计算机应该向超级用户警报并且关掉该单元并/或调度它-为维护之目的。
既然该操作是任务第一性的,那么就要求监督系统必须是高度可用的-这意味着无论何时在系统中的一台传感器管理器计算机出了问题,超级用户都应该能够无缝地切换到另一台机器以实现监视和积极的管理。因此,所有的管理器计算机必须实时地复制相同的传感器网络状态信息。注意,这种类型系统的特征-也就是,高可用性的要求和几千个(甚至更大数字)元素的存在-在现代网络管理中在其它一些情况下也是普通存在的。图2说明如此一个系统的概述-其中包含了簇能力。

图2.传感器监控系统概述
传统地,为了提供完全的持续性能力,必须设计专门的系统来显式地管理对象关系,就象在一个现代对象关系映射(ORM)的解决方案一样。并且在一个传统型实体持续性层风格设计中,你必须做到:
· 外在化关系映射(例如,在一个XML文件中)。
· 把对象分解成一些原型。
· 建立对象身份的概念以保留关系。
· 追踪使用中的字段(如果你想要避免整个的对串行化的代价)。
· 最后,把原始类型装配成对象。
然而,通过使用JBoss POJO缓存来管理你的对象状态,根本不存在上面提及的问题!说得更详细些,好处如下:
· 即时持续性(通过状态复制)-不修改你的域对象模型或指定复杂的对象关系映射。
· 可选的状态持续性也能够保存对象图。
· 可以批量实现良好粒度的复制(或持续性)-为优化网络交通。
如我们在上面描述的,在POJO缓存中的复制和/或持续性方面对用户是完全透明的。注意,对整个簇来说,还存在另一个方面-装载平衡或定位主和/或辅管理器-客户端GUI(对超级用户来说)和传感器都应该连接到其上。在此我们不讨论这些问题,而将只集中于讨论跨管理器的传感器网络状态的复制问题。
(二) 拓扑与对象建模
图3是我们的传感器监控系统示例的拓扑结构。基本上,在这个简化了的实例中,我们有两个站(Tokyo和Yokohama),而且在每一个站中,我们将有一个Wind和一个Rain传感器。对于每一种传感器,存在许多组件需要监控-例如,电源供应和传感器单元本身。我们的目标是高效地监控传感器-这是通过1)监视单个项的状态(例如,一个StateItem)以及它们的整个的状态(例如,Wind Summary);2)能够在运行时刻调入和调出单个传感器而不用重启簇管理器结点。

图3.传感器监控系统的拓扑

图4.传感器监控系统的类图
对于图3中的当前拓扑来说,Japan代表根结点,而Tokyo和Yokohama分别为站结点。不同的传感器(Rain或Wind)各用一个Node 对象来描述。然后,每个传感器有两个StateItems,也就是Power Supply和Sensor Unit。
这些结点之间的关系是双向的;我们可以从根结点一直导航到叶结点,或者我们也可以经由父结点往回导航。另外,还有一个WindSensor Summary和一个RainSensor Summary StateItem实例-它们参考各自的传感器。Summary项的目的是监控整个的Wind和Rain传感器单元的健康状态。结果是,该传感器的对象图中的对象是多参考的(显示于图2和3中)。
(三) 配置
在我们可以使用POJO缓存功能之前,我们需要使用JBoss AOP工具来重构这些POJO(也就是,PropagationManager,Node和StateItem类)。为此,我们可以经由XML声明或注解来实现。下面我们将展示经由JBoss AOP JDK 1.4注解(JDK 5.0注解将会在下一个JBoss缓存发行版本中得到支持)对POJO进行字节码重构。下面是针对三个主要接口的声明注解的代码片断:
/*** @@org.jboss.cache.aop.InstanceOfAopMarker*/
public interface PropagationManager {
public void setRootNode(String rdn);
public void addNode(String parentFdn, String rdn);
public void addStateItem(String parentFdn,long itemId, String name, long defaultState);
public Node findNode(String fdn);
public void stateChange(String fdn, long itemId,long newState);
...
}
/*** @@org.jboss.cache.aop.InstanceOfAopMarker*/
public interface Node {
public void addChildNode(Node child);
public List getChildren();
public void setParentNode(Node parent);
public Node getParentNode();
public void addStateItem(StateItem stateItem);
public void setSummaryStateItem(StateItem stateItem);
public StateItem getSummaryStateItem();
public List getStateItems();
public StateItem findStateItem(long itemId);
public void setPropagationRule(PropagationRule rule);
...
}
/*** @@org.jboss.cache.aop.InstanceOfAopMarker*/
public interface StateItem {
public long getItemId();
public boolean setState(long state);
public long getState();
public void setName(String name);
public String getName();
...
}
注意,在该JavaDoc中的注解-@@org.jboss.cache.aop.InstanceOfAopMarker是一个JBoss POJO缓存注解-它实质上声明这个接口的所有实例都将被进行字节码重构,因此不需要注解单个类。如果你想要注解一特定的类(而不涉及到它的子类),你也可以使用@@org.jboss.cache.aop.AopMarker注解。
在注解接口之后,我们使用一个JDK-1.4风格的JBoss AOP注解预编译器-annoc和一个AOP预编译器-aopc来执行编译时刻字节码重构。一旦完成这些步骤也就完成了字节码重构过程,然后我们就可以开始运行这个示例程序了。
