技术开发 频道

把JBoss缓存用作POJO缓存的实战演练


配置

  在我们可以使用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来执行编译时刻字节码重构。一旦完成这些步骤也就完成了字节码重构过程,然后我们就可以开始运行这个示例程序了。
 
代码片断
 
  下面是代码片段-它实例化一个PropagationManager实例并设置站点和传感器结点之间的正确关系。最后,我们使用TreeCacheAop API putObject()来把POJO(在这种情况中,是PropagationManager实例)放入缓存管理之中。之后,任何POJO操作都将被良好地粒度地复制;例如,一个setState()操作将只复制相应的状态字段(它是一个整数)。
 
protected void setUp() throws Exception {
 cache1_ = createCache("TestCluster");
 cache2_ = createCache("TestCluster");
 initPm();
}
protected void tearDown() throws Exception {
 cache1_.remove("/");
 cache1_.stop();
 cache2_.stop();
}
private TreeCacheAop createCache(String name) throws
Exception {
 //通过注入来配置缓存
 PropertyConfigurator config = new PropertyConfigurator();
 //读取replSync xml.
 //这里我们使用同步复制模式.
 config.configure(tree, "META-INF/replSync-service.xml");
 //我们可以设置一个不同的簇组.
 tree.setClusterName(name);
 tree.start(); //开始缓存
 return tree;
}
/***填充繁殖树*/
protected void initPm() throws Exception {
 pm_ = new PropagationManagerImpl();
 pm_.setRootNode("Japan");
 pm_.addNode("Japan", "Tokyo"); //东京站
 // Wind传感器设备
 pm_.addNode("Japan.Tokyo", "WindSensor1");
 pm_.addStateItem("Japan.Tokyo.WindSensor1", 1000,"power supply", 1040); //电源供应
 pm_.addStateItem("Japan.Tokyo.WindSensor1", 1001, "sensor unit", 1040); //传感器单位
 //Rain传感器设备
 pm_.addNode("Japan.Tokyo", "RainSensor1");
 pm_.addStateItem("Japan.Tokyo.RainSensor1", 1002,"power supply", 1040); //电源供应
 pm_.addStateItem("Japan.Tokyo.RainSensor1", 1003,"sensor unit", 1040); //传感器单位
 pm_.addNode("Japan", "Yokohama"); // 横滨站
 //Wind传感器设备
 pm_.addNode("Japan.Yokohama", "WindSensor2");
 pm_.addStateItem("Japan.Yokohama.WindSensor2", 1000,"power supply", 1040); //电源供应
 pm_.addStateItem("Japan.Yokohama.WindSensor2", 1001,"sensor unit", 1040); //传感器单位
 // Rain传感器设备
 pm_.addNode("Japan.Yokohama", "RainSensor2");
 pm_.addStateItem("Japan.Yokohama.RainSensor2", 1002,"power supply", 1040); //电源供应
 pm_.addStateItem("Japan.Yokohama.RainSensor2", 1003, "sensor unit", 1040);//传感器单位
 //网络中的Wind传感器的摘要结点
 pm_.createNode("WindSummary", "WindSummary");
 pm_.setUpperNode("WindSummary","Japan.Tokyo.WindSensor1"); //关联
 pm_.setUpperNode("WindSummary","Japan.Yokohama.WindSensor2"); //关联
 //网络中的Rain传感器的摘要结点
 pm_.createNode("RainSummary", "RainSummary");
 pm_.setUpperNode("RainSummary", "Japan.Tokyo.RainSensor1"); //关联
 pm_.setUpperNode("RainSummary","Japan.Yokohama.RainSensor2"); //关联
}
/**主启动点,由main来调用*/
public void testPropagation() throws Exception {
 //在此我们让POJO缓存来管理pm
 cache1_.putObject("/monitor", pm_);
 //输出
 printStatus("Initial state", pm_);
 // 从Manager #2检索POJO
 PropagationManager pm2 = (PropagationManager) cache2_.getObject("monitor");
 System.out.println( "---------------------------------------------");
 System.out.println("Modified on Manager #1");
 //该项中的一个状态被修改.
 //这将是良好粒度的复制
 pm_.stateChange("Japan.Tokyo.RainSensor1", 1003, 1041);
 printStatus("Japan.Tokyo.RainSensor1: id: 1003 state:
1040->1041 (retrieved from Manager #2!)", pm2);
 System.out.println( "---------------------------------------------");
 System.out.println("Modified on Manager #2");
 //该项中的一个状态被修改.
 //这将是良好粒度的复制.
 pm2.stateChange("Japan.Yokohama.WindSensor2",
 1001, 1041); //在缓存#2上修改状态
 printStatus("Japan.Yokohama.WindSensor2: id: 1001 state:
1040->1041 (retrieved from Manager #1!)", pm1);
 System.out.println( "---------------------------------------------");
 System.out.println( "Add a new VibrationSensor on Tokyo station");
 // Vibration传感器设备
 pm_.addNode("Japan.Tokyo", "VibrationSensor1");
 pm_.addStateItem("Japan.Tokyo.VibrationSensor1", 1004,"power supply", 1040); // 电源供应
 pm_.addStateItem("Japan.Tokyo.VibrationSensor1", 1005,"sensor unit", 1040); //传感器单位
 printStatus("Japan.Tokyo.VibrationSensor1: (retrieved from cache #2)", pm2);
}
public static void main(String[] args) throws Exception {
 PropagationReplAopTest pmTest =new PropagationReplAopTest();
 pmTest.setUp();
 pmTest.testPropagation();
 pmTest.tearDown();
}
 
  在上面的实例片断中,请注意下列几点:
 
  1.两个缓存实例被通过XML注入配置成功并且在随后启动。它们可以运行在两个独立的JVM中(并且在不同的机器上)。
 
  2.一个PropagationManager的实例经由一个putObject() API调用被放入到缓存管理中。此后,只需要单纯的POJO操作。例如,我们可以把额外的结点添加到PropagationManager实例上并且它将会相应地进行复制。
 
  3.经由一个getObject()调用,我们在缓存#2上检索PropagationManager的一个新实例。
 
  4. 各种setState()调用只会激活到其它的缓存实例的良好粒度的复制。
 
结果输出
 
  最后,当运行这个实例时,结果的输出如下所示:
 
Initial state
---------------------------------------------
Japan (Summary : 2000 [ok])
+ Tokyo (Summary : 2000 [ok])
+ + WindSensor1 (Summary : 2000 [ok])
+ + | ( name = power supply, id = 1000, state =1040)
+ + | ( name = sensor unit, id = 1001, state =1040)
+ + RainSensor1 (Summary : 2000 [ok])
+ + | ( name = power supply, id = 1002, state =1040)
+ + | ( name = sensor unit, id = 1003, state =1040)
+ Yokohama (Summary : 2000 [ok])
+ + WindSensor2 (Summary : 2000 [ok])
+ + | ( name = power supply, id = 1000, state =1040)
+ + | ( name = sensor unit, id = 1001, state =1040)
+ + RainSensor2 (Summary : 2000 [ok])
+ + | ( name = power supply, id = 1002, state =1040)
+ + | ( name = sensor unit, id = 1003, state =1040)
---------------------------------------------
Modified on Manager #1
StateItem.setState(): id: 1003 state changed \
from 1040 to 1041
……
 
  请注意其中加粗的几行。基本上,我们首先在管理器#1上进行了一个POJO操作setState,然后打印输出propagation(繁殖)树来验证状态被更新了,并且反过来也如此。如此重复是值得的,尽管没有显示在复制层数据流的输出结果中,但是每一个setState()操作也将会只激活具有良好粒度的字段级复制。另外,如果该调用是在一个事务上下文中,那么更新将会被批量地进行;也就是说,只要准备好提交时才进行复制。最后,还要注意,我们已经能够轻松地把一个新的传感器添加到网络中。一个传统型的系统一般都要求某种类型的重启机制。
 
总结
  在本文中,我们分析了通过平衡TreeCacheAop组件来实现用JBoss缓存担任POJO缓存的能力。通过使用POJO缓存功能,它能够为POJO提供无缝的持续性存储的能力-在保留对象-图关系的同时又能实现良好粒度的复制。
0
相关文章