标准MBean所暴露的属性,操作,通知都是固定不变的,都固化在ClassNameMBean这个接口中,灵活度不足。

动态Mbean所暴露的特性是运行时确立,灵活度足够,但编码困难,因为你需要编码实现每一个属性,操作与通知。

模型Mbean也是一种动态Mbean,能够使你更快的编写动态MBean.

模型MBean的封装类RequiredModelMBean实现了ModelMBean接口,ModelMBean接口继承自DynamicMBean,所以说模型Mbean也是一种动态Mbean

首先定义需要管理的资源:

   
   
   
   
  1. package guojje.jmx;  
  2.  
  3. import javax.management.NotificationBroadcasterSupport;  
  4.  
  5. public class HelloWordShadow extends NotificationBroadcasterSupport{  
  6.       
  7.     private String name = "anranran";  
  8.     public HelloWordShadow(String name){  
  9.         this.name = name;  
  10.     }  
  11.       
  12.     public String getName(){  
  13.         System.out.println("invoke getName method!!");  
  14.         return name;  
  15.     }  
  16.       
  17.     public void setName(String name){  
  18.         System.out.println("invoke setName method!!");  
  19.         this.name = name;  
  20.     }  
  21.       
  22.     public void Say(){  
  23.         System.out.println("hi~!!!");  
  24.     }  
  25. }  

测试类:

   
   
   
   
  1. package guojje.jmx;  
  2. public class Main {  
  3.     public static void main(String args[]) throws Exception {  
  4.         JMXServiceURL jUrl = new JMXServiceURL("iiop""192.168.1.61"9998,  
  5.                 "/jndi/rmi://localhost:9999/guojje");  
  6.         MBeanServer ms = MBeanServerFactory.createMBeanServer();  
  7.         JMXConnectorServer cs = JMXConnectorServerFactory  
  8.                 .newJMXConnectorServer(jUrl, null, ms);  
  9.         cs.start();  
  10.         System.out.println("jmx address:" + cs.getAddress());  
  11.  
  12.         exeHelloWordShadow(ms);  
  13.     }  
  14. private static void exeHelloWordShadow(MBeanServer ms) throws Exception {  
  15.         RequiredModelMBean rmm = new RequiredModelMBean();  
  16.         //add a property called 'name'  
  17.         ModelMBeanAttributeInfo nameAttr = new ModelMBeanAttributeInfo("name","java.lang.String",  
  18.                 "pepole name",truetruefalse,null);  
  19.           
  20.         ModelMBeanInfo mmInfo = new ModelMBeanInfoSupport(RequiredModelMBean.class.toString(), "Jmx demo"new ModelMBeanAttributeInfo[]{nameAttr}, nullnullnull);  
  21.         rmm.setModelMBeanInfo(mmInfo);  
  22.     //System.out.println(nameAttr.getDescriptor().getFieldValue("value"));//1  
  23.         rmm.setAttribute(new Attribute("name""guojianjun"));  
  24.         System.out.println(rmm.getAttribute("name"));  
  25.     //System.out.println(nameAttr.getDescriptor().getFieldValue("value")); //2  
  26. }  

目前nameHelloWorkShadow还没有任何关系,去掉12两行注释,你会发现ModelMBeanAttributeInfo的描述子用来存储了这个值(代码中,ModelMBeanAttributeInfo的最后一个参数,我设了null,JDK会为之创建一个默认的描述子)。
 

如何把对MBean的操作转移动对HelloWordShadow的操作,以达到我们管是资源的目的。

第一步为ModelMBeanAttributeInfo对像添加get,set方法.

   
   
   
   
  1. private static void exeHelloWordShadow(MBeanServer ms) throws Exception {  
  2. RequiredModelMBean rmm = new RequiredModelMBean();  
  3.         Method getMethod = HelloWordShadow.class.getMethod("getName",  
  4.                 new Class[] {});  
  5.         Method setMethod = HelloWordShadow.class.getMethod("setName",  
  6.                 new Class[] {String.class});  
  7.         //add a property called 'name'  
  8.         ModelMBeanAttributeInfo nameAttr = new ModelMBeanAttributeInfo("name",  
  9.                 "pepole name",getMethod, setMethod,null);  
  10.           
  11.           
  12.           
  13.         ModelMBeanInfo mmInfo = new ModelMBeanInfoSupport(RequiredModelMBean.class.toString(), "Jmx demo", new ModelMBeanAttributeInfo[]{nameAttr}, null, null, null);  
  14.         rmm.setModelMBeanInfo(mmInfo);  
  15.           
  16.         rmm.setAttribute(new Attribute("name", "guojianjun"));  
  17.         System.out.println(rmm.getAttribute("name"));   

运行结果:

jmx address:service:jmx:iiop://192.168.1.61:9998/jndi/rmi://localhost:9999/guojje

guojianjun

发现并没有起作用。刚才说到ModelMBeanAttributeInfo用了默认的描述子,我们不防给

添加一个描述子:

   
   
   
   
  1. private static void exeHelloWordShadow(MBeanServer ms) throws Exception {  
  2.     .....
  3. Descriptor nameDesc = new DescriptorSupport();  
  4.         nameDesc.setField("name""Name");//must be setted  
  5.         nameDesc.setField("descriptorType""attribute");//must be setted  
  6.         nameDesc.setField("displayName""Name");  
  7.         nameDesc.setField("getMethod""getName");  
  8.         nameDesc.setField("setMethod""setName");  
  9.         //add a property called 'name'  
  10.         ModelMBeanAttributeInfo nameAttr = new ModelMBeanAttributeInfo("name",  
  11.                 "pepole name",getMethod, setMethod,nameDesc);  
  12.           
  13.         ModelMBeanInfo mmInfo = new ModelMBeanInfoSupport(null"Jmx demo"new ModelMBeanAttributeInfo[]{nameAttr}, nullnullnull);  
  14.         rmm.setModelMBeanInfo(mmInfo);  
  15.           
  16.         rmm.setAttribute(new Attribute("name""guojianjun"));  
  17.         System.out.println(rmm.getAttribute("name"));  

更糟糕,直接报错:Operation setName not in ModelMBeanInfo

但这也说明是用描述子设定set方法是正确的。这样我们需要在ModelMBeanInfo中声明setName操作,getName一样: 

   
   
   
   
    .....
  1. //add a property called 'name'  
  2.         ModelMBeanAttributeInfo nameAttr = new ModelMBeanAttributeInfo("name",  
  3.                 "pepole name",getMethod, setMethod,nameDesc);  
  4.           
  5.          //parameter is not necessary  
  6.          ModelMBeanOperationInfo getName = new ModelMBeanOperationInfo(//  
  7.                     "getName"//  
  8.                     "get name attribute"//  
  9.                     null//  
  10.                     "java.lang.String"//  
  11.                     MBeanOperationInfo.ACTION, //  
  12.                     null//  
  13.                   );   
  14.            
  15.          MBeanParameterInfo mParam = new MBeanParameterInfo("name""java.lang.String""set name methord param");  
  16.            
  17.          ModelMBeanOperationInfo setName = new ModelMBeanOperationInfo(//  
  18.                     "setName"//  
  19.                     "set name attribute"//  
  20.                     new MBeanParameterInfo[]{mParam}, //  
  21.                     null//  
  22.                     MBeanOperationInfo.ACTION, //  
  23.                     null//  
  24.           );   
  25.           
  26.         ModelMBeanInfo mmInfo = new ModelMBeanInfoSupport(null"Jmx demo"new ModelMBeanAttributeInfo[]{nameAttr},   
  27.                 null , new ModelMBeanOperationInfo[]{getName,setName}, null);  
  28.         rmm.setModelMBeanInfo(mmInfo);  
  29.           
  30.         rmm.setAttribute(new Attribute("name""guojianjun"));  
  31.         System.out.println(rmm.getAttribute("name"));  

仍然报错: managedResource for invoke setName is null

managedResource是什么?就是我们需要管理的对像资源,在这里当然是HelloWordShadow对象,终于扯上关系了。那就构造一个HelloWordShadow对象:

   
   
   
   
  1. .....
  2. ModelMBeanInfo mmInfo = new ModelMBeanInfoSupport(RequiredModelMBean.class.toString(), "Jmx demo"new ModelMBeanAttributeInfo[]{nameAttr},   
  3.                 null , new ModelMBeanOperationInfo[]{getName,setName}, null);  
  4.         rmm.setModelMBeanInfo(mmInfo);  
  5.           
  6.         HelloWordShadow hw = new HelloWordShadow("miniName");  
  7.         rmm.setManagedResource(hw, "ObjectReference");  
  8.           
  9.         rmm.setAttribute(new Attribute("name""guojianjun"));  
  10.         System.out.println(rmm.getAttribute("name"));  

运行输出:

jmx address:service:jmx:iiop://192.168.1.61:9998/jndi/rmi://localhost:9999/guojje

invoke getName method!!

invoke setName method!!

invoke getName method!!

guojianjun

OK,成功。说了这么多,那构造函数ModelMBeanAttributeInfo("name",         "pepole name",getMethod, setMethod,nameDesc);里的getMethod, setMethod方法有什么用呢,我觉得好像没什么用,只是用来确认属性类型,可读可写情况。(个人观点)

最后就是把这个MBean注册到MBeanServer中管理,Jconsole就可以看到了:

ms.registerMBean(rmm, new ObjectName(

       "guojje:type=notification,name=hello"));

(待续)