JMX 代理中模型 MBean 的运行时挂接
当您使用 ModelMBean 实现时,唯一必需的工作就是向 ModelMBean “封装器”实例提供合适的 ModelMBeanInfo 结构。清单 8 显示了来自 BaseModAgent 类的摘录:
清单 8. BaseModAgent.java 中 RequiredModelMBean 的运行时挂接
2 ObjectName tpMBeanName = new ObjectName("MBean:name=ClickMeter");
3 RequiredModelMBean modelmbean =
4 new RequiredModelMBean(createMBeanInfo());
5 modelmbean.setManagedResource(inManagedObj, "objectReference");
6 server.registerMBean(modelmbean, tpMBeanName);
7 } catch (Exception e) {
8 System.out.println("Cannot register ClickMeter MBean!");
9 e.printStackTrace();
10 return;
11 }
12
在清单 8 中,通过对本地 createMBeanInfo() 方法的调用对 javax.management.modelmbean.RequiredModelMBean 进行实例化。这种方法将创建描述由 MBean 公开的属性、操作和事件的元数据。另外请注意我们调用了 RequiredModelMBean 的 setManagedResource() 方法,向它提供 ClickMeterMod 这一“要封装的类”的引用。事实上,通过使用 JMX 参考实现,该引用还可以是 RMI 引用或 CORBA IOR - 允许使用 ModelMBean 方便地“工具化”远程资源。最后,请注意当我们在 MBeanServer 上调用 registerMBean() 时,我们注册的是 RequiredModelMBean 封装器实例,而不是非 MBean 的 ClickMeterMod 。图 6 显示了 RequiredModelMBean 在运行时期间是如何工作的:
图 6. RequiredModelMBean 的运行时操作
图 6 说明了代理层如何只与 RequiredModelMBean 实例一起工作,而 RequiredModelMBean 实例又依次将属性的访问和操作映射到真正封装的 ClickMeterMod 类。这就减轻了对部分封装类的 JMX 相关性的任何要求。
填充 ModelMBean 元数据
实例化 RequiredModelMBean 实例时会向其提供元数据描述符。该描述符是 javax.management.modelmbean.ModelMBeanInfo 类的实例。它包含关于封装类公开的属性、操作和事件的全部信息(而且,更重要的是,还包含 RequiredModelMBean 应如何访问它们的信息)。 RequiredModelMBean 将在运行时生成它自己的元数据以代表封装类支持 DynamicMBean 接口。清单 9 显示了 createMBeanInfo() 方法中的这段代码:
清单 9. 在 createMBeanInfo() 方法中创建 ModelMBean 元数据
2 Descriptor atDesc = new DescriptorSupport(new String[] {
3 "name=PanelValue",
4 "descriptorType=attribute",
5 "default=0",
6 "displayName=Value of the Panel",
7 "getMethod=getPanelValue",
8 "setMethod=setPanelValue"
9 }
10 );
11 ModelMBeanAttributeInfo [] mmbai = new ModelMBeanAttributeInfo[1];
12 mmbai[0] = new ModelMBeanAttributeInfo("PanelValue","java.lang.Integer",
13 "The ClickMeter Value", true,true, false, atDesc);
14 ModelMBeanOperationInfo [] mmboi = new ModelMBeanOperationInfo[4];
15 mmboi[0] = new ModelMBeanOperationInfo("incPanelValue",
16 "increment the meter value", null, "void", ModelMBeanOperationInfo.ACTION
17 );
18 mmboi[1] = new ModelMBeanOperationInfo("decPanelValue",
19 "decrement the meter value", null, "void", ModelMBeanOperationInfo.ACTION
20 );
21 mmboi[2] = new ModelMBeanOperationInfo("getPanelValue",
22 "getter for PanelValue", null,"Integer", ModelMBeanOperationInfo.INFO);
23 MBeanParameterInfo [] mbpi = new MBeanParameterInfo[1];
24 mbpi[0] = new MBeanParameterInfo("inVal", "java.lang.Integer",
25 "value to set");
26 mmboi[3] = new ModelMBeanOperationInfo("setPanelValue",
27 "setter for PanelValue", mbpi, "void", ModelMBeanOperationInfo.ACTION);
28 ModelMBeanConstructorInfo [] mmbci = new ModelMBeanConstructorInfo[1];
29 mmbci[0] = new ModelMBeanConstructorInfo("ClickMeterMod",
30 "constructor for Model Bean Sample", null);
31 return new ModelMBeanInfoSupport("dwjmxservice.basic.ClickMeterMod",
32 "dw ModelMBean example", mmbai, mmbci, mmboi, null);
33 }
34
在清单 9 中要注意的重要特性是 javax.management.modelmbean.ModelMBeanInfoSupport 类如何提供现成可用的 MBeanInfo 实现。事实上,整个方法都在处理这个支持类实例的实例化工作。要对它适当进行实例化,您必须提供封装类的完全限定名称以及描述,然后是指定将要公开的属性、构造器、操作和事件的四个附加参数。该方法的大多数代码主要是创建 ModelMBeanAttributeInfo 、 ModelMBeanConstructorInfo 和 ModelMBeanOperationInfo 数组,这些数组都是 ModelMBeanInfoSupport 类构造器的参数。请注意,用于 PanelValue 属性的 getter 方法和 setter 方法在操作的元数据中被再次定义。这是必需的,因为在封装类中不要求遵循词法模式(命名约定)。另外, RequiredModelMBean 信任所提供的元数据并且将不在封装类上执行额外的内省(如果引用是远程的或是基于 CORBA 的,那么这个操作甚至是不可能的)。
测试基于模型 MBean 的工具
使用 compile.bat 文件编译模型 MBean 示例,或者执行下列命令行:
2 <jmx install dir>\lib\jmxri.jar;
3 <jmx install dir>\lib\jmxtools.jar
4 -d classes src\dwjmxservice\basic\*.java
5
6
使用 runmod.bat 文件运行模型 MBean 示例,或者从代码子目录执行下列命令行:
java -classpath
classes dwjmxservice.basic.ClickMeterMod
当您使用 HTTP 协议适配器测试这个 MBean 时,请注意从代理操作的角度来看,它几乎没什么不同。唯一的区别是,用于 PanelValue 的 getter 方法和 setter 方法操作还可以通过 Web 页面独立地使用。
不必使用 RequriedModelMBean 类对 JMX 执行“快速修改”,您可以通过对 DynamicMBean 接口直接编码来创建灵活得多的动态 MBean。