隨筆 - 12, 文章 - 0, 評論 - 22, 引用 - 0
          數據加載中……

          JMX分析1-MBean的實現

                本文只是JDK7中JMX在本地,MBeanServer管理MBeans的默認實現的探索學習,沒有涉及JMX Remote。
                JMX 使用了 Java Bean 模式來傳遞信息。一般說來,JMX 使用有名的 MBean,其內部包含了數據信息,這些信息可能是:應用程序配置信息、模塊信息、系統信息、統計信息等。另外,MBean 也可以設立可讀寫的屬性、直接操作某些函數甚至啟動 MBean 可發送的 notification 等。MBean 包括 Standard,MXBean,Dynamic,Model,Open 等幾種分類,其中最簡單是標準 MBean 和 MXBean,而我們使用得最多的也是這兩種。MXBean 主要是 java.lang.management使用較多,將在下一節中介紹。我們先了解其他一些重要的 MBean 的種類。

          StandardMBean
               MXBean 規定了標準 MBean 也要實現一個接口,所有向外界公開的方法都要在這個接口中聲明。否則,管理系統就不能從中獲得相應的信息。此外,該接口的名字也有一定的規范:即在標準 MBean 類名之后加上“MBean”后綴。若 MBean 的類名叫做 MBeansName 的話,對應的接口就要叫做 MBeansNameMBean。
          例子:
           1 package test.jmx;
           2 
           3 import javax.management.Notification;
           4 import javax.management.NotificationBroadcasterSupport;
           5 
           6 
           7 /**
           8  * 此標準MBean需實現XXXMBean這樣名稱的借口,XXX為這個類的名稱,
           9  * 如果MBean需要消息事件的發送、監聽等需要實現
          10  *  @see javax.management.NotificationBroadcaster,
          11  * 或者繼承@see javax.management.NotificationBroadcasterSupport
          12 
          13  */
          14 public class HelloWorld extends NotificationBroadcasterSupport implements HelloWorldMBean {
          15     public String hello;
          16     
          17     private long seq = 0l;
          18 
          19     public HelloWorld() {
          20         this.hello = "Hello World! I am a Standard MBean";
          21     }
          22 
          23     public HelloWorld(String hello) {
          24         this.hello = hello;
          25     }
          26 
          27     public String getHello() {
          28         return hello;
          29     }
          30 
          31     @Override
          32     public Object getInstance() {
          33         return new Object();
          34     }
          35 
          36     /* 
          37      * 當執行message的時候,發送一個消息(事件)
          38      * @see test.jmx.HelloWorldMBean#message(java.lang.String)
          39      */
          40     @Override
          41     public String message(String ms) {
          42         Notification notice = new  Notification("type1",this,seq++," the message metheod is invoked,the argument ms: "+ms);
          43         sendNotification(notice);
          44         return " the message :  ";
          45     }
          46 
          47     @Override
          48     public void setHello(String hello) {
          49         this.hello = hello;
          50     }
          51 }
          52 

           1 
           2 package test.jmx;
           3 
           4 public interface HelloWorldMBean {
           5     public String getHello();
           6     
           7     public void setHello(String hello);
           8     
           9     public Object getInstance();
          10     
          11     public String message(String ms);
          12 
          13 }
          14 

          測試 :
            1 package test.jmx;
            2 
            3 import java.util.Set;
            4 
            5 import javax.management.Attribute;
            6 import javax.management.MBeanOperationInfo;
            7 import javax.management.MBeanServer;
            8 import javax.management.MBeanServerFactory;
            9 import javax.management.Notification;
           10 import javax.management.NotificationListener;
           11 import javax.management.ObjectInstance;
           12 import javax.management.ObjectName;
           13 import javax.management.modelmbean.RequiredModelMBean;
           14 
           15 import org.junit.Test;
           16 
           17 public class JmxTest {
           18     
           19     /**
           20      * 測試標準MBean
           21      * 需要被管理的方法、屬性等在接口中定義好,創建一個類,繼承此接口,然后實現時候方法, 
           22      * 這樣,但注冊到MBeanServer的時候,會自動管理其,接口中的各個屬性、方法。
           23      * @throws Exception
           24      */
           25     @Test
           26     public void test1StandardMBean() throws Exception{
           27 //        MBeanServer ms = MBeanServerFactory.createMBeanServer("JMX2Test");
           28         MBeanServer ms = MBeanServerFactory.createMBeanServer();
           29         ObjectName name = new ObjectName("Hello:type=myfirstMbean");
           30         
           31 //        ms.createMBean("HelloWorld", objectName);
           32         HelloWorld hello = new HelloWorld(" yao yao , qie ke nao ");
           33         
           34         //MBean需要實現NotificationBroadcaster接口,支持各種事件的發送和處理
           35         hello.addNotificationListener(new NotificationListener() {
           36             @Override
           37             public void handleNotification(Notification notification, Object handback) {
           38                 System.out.println(" access listen : "+notification);
           39             }
           40         },null,null);
           41         
           42         ms.registerMBean(hello,name );
           43         
           44         String s1 = (String)ms.getAttribute(name, "Hello");
           45         System.out.println(" the init value : "+s1);
           46         
           47         ms.setAttribute(name, new Attribute("Hello"," hi ,hi ,man "));
           48         String s2 = (String)ms.getAttribute(name, "Hello");
           49         System.out.println(" the init value : "+s2);
           50         
           51         ms.invoke(name, "message", new Object[]{" i as message "}, new String[]{"java.lang.String"});
           52 
           53         ObjectName name2 = new ObjectName("*:*");
           54         Set<ObjectInstance> set = ms.queryMBeans(name2, null);
           55     }
           56     
           57     /**
           58      * 動態Mbean,需要實現DynamicMBean接口,并且任何需要,管理的方法、屬性,都需要在接口的方法中,
           59      * 自己來實現,Mbeaninfo也需要自己設置,這樣編程的工作量大,但是有很大的可控性。
           60      * @throws Exception
           61      */
           62     @Test
           63     public void test2DynamicMBean() throws Exception{
           64         HelloWorldDynamic dynamic = new HelloWorldDynamic();
           65         
           66         MBeanServer ms = MBeanServerFactory.createMBeanServer();
           67         //創建一個ObjectName
           68         ObjectName name = new ObjectName("DynamicHello:type=dinamicMbean");
           69         
           70         //注冊動態MBean到MBeanServer服務上去
           71         ms.registerMBean(dynamic, name);
           72         
           73         //得到屬性值
           74         Object o = ms.getAttribute(name, "getInstance");
           75         String hello = (String)ms.getAttribute(name, "gh");
           76         MBeanOperationInfo operation = dynamic.getMBeanInfo().getOperations()[0];
           77         System.out.println(" attribute value of getInstance:"+o+"; attribute value of gh:"+hello);
           78         
           79         //執行一個方法(操作)
           80         ms.invoke(name, operation.getName(), nullnull);
           81     }
           82     
           83     @Test
           84     public void test3RequiredModelMBean() throws Exception{
           85         HelloWorldModelMBean hello = new HelloWorldModelMBean();
           86         
           87         MBeanServer ms = MBeanServerFactory.createMBeanServer();
           88         RequiredModelMBean modelMbean = hello.createModelBean();
           89         ObjectName name = new ObjectName("RequiredMBeanHello:type=ModelMbean");
           90         //監聽屬性變化事件
           91         modelMbean.addAttributeChangeNotificationListener(new NotificationListener() {
           92             @Override
           93             public void handleNotification(Notification notification, Object handback) {
           94                 System.out.println(" --Attribute已經改變-- ");
           95             }
           96         }, null,null);
           97         ms.registerMBean(modelMbean, name);
           98         
           99         ms.invoke(name, "setHello", new Object[]{" aaa "},new String[]{ "java.lang.String"});
          100         String s = (String)ms.getAttribute(name, "hello");
          101         //出發Attribute改變事件
          102         ms.setAttribute(name, new Attribute("hello", "bbb"));
          103         String s2 = (String)ms.getAttribute(name, "hello");
          104         System.out.println(s);
          105         System.out.println(s2);
          106     }
          107 }
          108 
               
          • MBean注冊
          圖:一個MBean被注冊進MBeanServer的流程圖


          JmxMBeanServer在register一個MBean的時候,主要的步驟:
          1. 查看MBean是否符合命名規則
          2. 創建一個DynamicMBean,如果需要注冊的是標準MBean,那么通過內省機制,得到標準的MBean各種元數據,這些數據封裝組合到MBeanInfo中,接著創建StandardMBeanSupport(StandardMBeanSupport是DynamicMBean的子類) 。
          3. JMX中按照ObjectName加上一次創建好的DynamicMBean,存入到Repository,Repository存的格式有點相當于Map的(key,value)。

          • MBeanServer的管理MBean分析
          代碼:MBeanServer.getAttribute(ObjectName name, String attribute)執行部分源碼
           1  JmxMBeanServer:
           2       public Object getAttribute(ObjectName name, String attribute)
           3           throws MBeanException, AttributeNotFoundException,
           4                  InstanceNotFoundException, ReflectionException {
           5             //mbsInterceptor類型為DefaultMBeanServerInterceptor,也實現了MBeanServer接口,
           6             //JmxMBeanServer實現的MBeanServer接口的方法,基本都是由mbs代理執行的。
           7           return mbsInterceptor.getAttribute(cloneObjectName(name), attribute);
           8       }
           9   
          10 DefaultMBeanServerInterceptor:
          11      public Object getAttribute(ObjectName name, String attribute)
          12          throws MBeanException, AttributeNotFoundException,
          13                 InstanceNotFoundException, ReflectionException {       
          14 
          15          //通過ObjectName(key)從Repository中得到注冊過的MBean
          16          final DynamicMBean instance = getMBean(name);
          17 
          18           //得到Attribute的值
          19           return instance.getAttribute(attribute);
          20     }
          21 StandardMBeanSupport:
          22     public final Object gtAttribute(String attribute)
          23             throws AttributeNotFoundException,
          24                    MBeanException,
          25                    ReflectionException {
          26         return perInterface.getAttribute(resource, attribute, getCookie());
          27     }  
          28 PerInterface:
          29     Object getAttribute(Object resource, String attribute, Object cookie)
          30             throws AttributeNotFoundException,
          31                    MBeanException,
          32                    ReflectionException {
          33         //得到Attribute屬性的方法,也就是MBean接口中定義的getXXX()方法
          34         final M cm = getters.get(attribute);
          35         if (cm == null) {
          36             final String msg;
          37             if (setters.containsKey(attribute))
          38                 msg = "Write-only attribute: " + attribute;
          39             else
          40                 msg = "No such attribute: " + attribute;
          41             throw new AttributeNotFoundException(msg);
          42         }
          43         //在調用進去的話,就是通過反射調用cm方法,得到屬性的值
          44         return introspector.invokeM(cm, resource, (Object[]) null, cookie);
          45     }

          其他的比如setAttribute(...),和invoke(...)方法就是把上個getAttribute(...)替換相應方法名就可以了。
          參照上面流程圖和JDK中JMX的實現,可以看出JMX在內部實現中,對于標準MBean,也是轉換成DynamicMBean(StandardMBeanSupport是DynamicMBean的子類)。

          • 相關的類說明
          MBeanServerConnection、  MBeanServer、JmxMBeanServer,DefaultMBeanServerInterceptor:
          MBeanServerConnection提供一種連接到MBeanServer的途徑,可以使本地的或者遠程的。MBeanServer是作為一個本地的MBeanServerConnection,用于管理MBean的一個服務。主要提供創建、注冊、移除MBean,MBean屬性的獲得和設置,MBean的操作(invoke),消息機制的支持,MBean的查詢,MBean信息的展示。但是MBeanServer雖然目的是管理和對注冊進來的MBean進行操作,但是沒有方法是可以直接得到MBean實例的,只能通過MBeanServer對MBean進行操作。
          圖:MBeanServer結構

          圖:MBeanServer屬性


          PerInterface:
          在JMX內省一個MBean的時候,代表了MBean實現的MBean接口的行為。其中的屬性getters代表了MBean接口的getXXX方法,setters代表了MBean接口的setXXX方法,ops代表了MBean的其他方法。MBean接口中的getXXX()和setXXX()方法,在標準MBean中代表了一個屬性的讀和寫,而其他的方法名,則代表著一個操作。MBeanServer調用的方式是不一樣的,前者調用getAttbute(...)和setAttbute(...),而后者是調用invoke(...);
          圖:PerInterface結構


          MBeanInfo、MBeanAttributeInfo、MBeanConstructorInfo、MBeanNotificationInfo、MBeanOperationInfo:
                  這些類構成了MBean的所有信息。JMX利用Introspection機制分析MBean的數據,得到此MBean的元數據(i.e. 描述一個方法、屬性的名稱、類型、返回值等)。
          MBeanAttributeInfo用于存放屬性相關的元數據,MBeanConstructorInfo用于存放跟構造器相關的元數據,MBeanOperationInfo用于存放操作相關的元數據,MBeanNotificationInfo用于存放JMX消息(事件)相關的元數據。MBeanInfo就是存放所有的這些元數新,JMX管理系統如果想知道一個MBean能管理的屬性或者能進行什么用的操作,那么都可以從MBeanInfo中獲得信息。

          圖:MBeanInfo構成

          NotificationBroadcasterSupport、NotificationListener、NotificationFilter、NotificationBroadcaster:
          這些類就是提供MBean的消息機制。給予一個MBean發送消息,過濾消息、監聽消息,執行消息等。一個MBean需要消息功能的話,就需要實現以后這些類。

          圖:消息機制的結構

          Introspector、MBeanIntrospector:
          JMX用這兩個類進行內省,即通過他們能分析MBean的所有屬性、方法,然后進行封裝、轉化、存儲等,轉化成我們需要的數據結構

          MBeanRegistration :
          用于一個MBean在注冊前后,或者注銷前后,做一些邏輯操作
          圖:MBeanRegistration結構圖  


          Dynamic、MBeanSupport、StandardMBeanSupport、MXBeanSupport:
          即使MBean是標準形式的,但是JMX實現中,還是會生成一個動態的MBean,即StandardMBeanSupport,來封裝標準MBean。
          圖:Dynamic、MBeanSupport、StandardMBeanSupport、MXBeanSupport關系圖(列出部分屬性、接口)

                 
                 總結:標準MBean按照一定編程規則(i.e. getXXX(),setXXX()),把需要管理的標準MBean的屬性和操作,加入到接口的方法中,然后標準MBean實現這個接口,這樣當標準MBean注冊到MBeanServer中后,MBeanServer就可以管理此MBean了。標準MBean在于想要新增一個管理的屬性或操作,都要先在接口中先新增一個方法,然后實現。

          DynamicMBean
          JMX管理的MBean除了標準MBean外,還可以是DynamicMBean。只要我們實現此接口,就可以被JMX Server管理。
          例子:
           1 package test.jmx;
           2 
           3 import java.lang.reflect.Method;
           4 
           5 import javax.management.Attribute;
           6 import javax.management.AttributeList;
           7 import javax.management.AttributeNotFoundException;
           8 import javax.management.DynamicMBean;
           9 import javax.management.InvalidAttributeValueException;
          10 import javax.management.MBeanAttributeInfo;
          11 import javax.management.MBeanException;
          12 import javax.management.MBeanInfo;
          13 import javax.management.MBeanOperationInfo;
          14 import javax.management.ReflectionException;
          15 
          16 public class HelloWorldDynamic implements DynamicMBean {
          17     public String hello;
          18     
          19 
          20     public HelloWorldDynamic() {
          21         this.hello = "Hello World! I am a Dynamic MBean";
          22     }
          23 
          24     public HelloWorldDynamic(String hello) {
          25         this.hello = hello;
          26     }
          27 
          28     public String getHello() {
          29         return hello;
          30     }
          31 
          32     public Object getInstance() {
          33         return new Object();
          34     }
          35 
          36     public void setHello(String hello) {
          37         this.hello = hello;
          38     }
          39 
          40     @Override
          41     public Object getAttribute(String attribute)
          42             throws AttributeNotFoundException, MBeanException,
          43             ReflectionException {
          44         //設置getAttribute的執行邏輯
          45         if("getInstance".equals(attribute)){
          46             return getInstance();
          47         }
          48         
          49         return null;
          50     }
          51 
          52     @Override
          53     public AttributeList getAttributes(String[] attributes) {
          54         // TODO Auto-generated method stub
          55         return null;
          56     }
          57 
          58     MBeanInfo info = null;
          59     @Override
          60     public MBeanInfo getMBeanInfo()  {
          61         try {
          62             Class cls = this.getClass();
          63             // 用反射獲得 "getHello" 屬性的讀方法
          64             //DynamicMBean中,
          65             Method readMethod = cls.getMethod("getHello", new Class[0]);
          66             MBeanAttributeInfo attribute = new MBeanAttributeInfo("gh",
          67                     " the first attribute ", readMethod, null);
          68             //執行java類的method需要的一些元數據,由MBeanOperationInfo提供
          69             MBeanOperationInfo operation = new MBeanOperationInfo(
          70                     " the first operation ", cls.getMethod("getInstance", null));
          71             info = new MBeanInfo(cls.getName(), " this is a dynamic MBean ",
          72                     new MBeanAttributeInfo[] { attribute }, null,
          73                     new MBeanOperationInfo[] { operation }, null);
          74         } catch (Exception e) {
          75             System.out.println(e);
          76         }
          77         return info;
          78     }
          79 
          80     @Override
          81     public Object invoke(String actionName, Object[] params, String[] signature)
          82             throws MBeanException, ReflectionException {
          83         System.out.println(" the HelloWorldDynamic's method invoke  ");
          84         return null;
          85     }
          86 
          87     @Override
          88     public void setAttribute(Attribute attribute)
          89             throws AttributeNotFoundException, InvalidAttributeValueException,
          90             MBeanException, ReflectionException {
          91         
          92     }
          93 
          94     @Override
          95     public AttributeList setAttributes(AttributeList attributes) {
          96         return null;
          97     }
          98 }
          99 

          測試此MBean請看JmxTest類中的test2DynamicMBean()。

                 當實現一個DynamicMBean,我們需要寫的代碼量是非常多的,MBeanInfo的信息,需要自己編碼,而且對于MBeanServer操作MBean的方法,也得自己重載實現。在動態MBean中,MBeanInfo里面的信息,主要用來展示的,具體的對DynamicMBean的操作是自己實現的。DynamicMBean的優點是對于邏輯控制是可以很靈活的。而不像標準MBean一樣,所有的操作或屬性需要在MBean接口中定義。在jdk中JMX實現DynamicMBean的流程是非常簡單的,Jmx server對于DynamicMBean的操作也是非常簡單的,相對于標準MBean,注冊的時候少了內省的步驟;其他的操作跟標準MBean一樣,只是對于getAttribute(...),setAttribute(...),invoke(...)等一些的操作都是需要自己來實現的。

          ModelMBean
                然而,普通的動態 Bean通常缺乏一些管理系統所需要的支持:比如持久化MBean的狀態、日志記錄、緩存等等。如果讓用戶去一一實現這些功能確實是件枯燥無聊的工作。為了減輕用戶的負擔,JMX提供商都會提供不同的 ModelBean實現。其中有一個接口是 Java 規范中規定所有廠商必須實現的:javax.management.modelmbean.RequiredModelBean。通過配置Descriptor信息,我們可以定制這個ModelBean,指定哪些 MBean狀態需要記入日志、如何記錄以及是否緩存某些屬性、緩存多久等等。對于Descriptor,在MBean中相當于附帶的一些信息,這些信息在MBean實現中可以作為一種策略,以此增強MBean的功能。動態MBean以及標準MBean的MBeanInfo都已經包括了Descriptor,但是在邏輯實現中沒用到此對象。在ModelMBean中,Descriptor作用非常大,持久化、日志、緩存等的策略等相關信息都是在Descriptor中定義的。開發人員可以增加相關屬性到Descriptor中,來對應用功能進行擴展 
          這里,我們以 RequiredModelBean 為例討論 ModelBean。
          例子:
            1 package test.jmx;
            2 
            3 import java.lang.reflect.Constructor;
            4 
            5 import javax.management.Descriptor;
            6 import javax.management.InstanceNotFoundException;
            7 import javax.management.MBeanException;
            8 import javax.management.MBeanOperationInfo;
            9 import javax.management.MBeanParameterInfo;
           10 import javax.management.RuntimeOperationsException;
           11 import javax.management.modelmbean.DescriptorSupport;
           12 import javax.management.modelmbean.InvalidTargetObjectTypeException;
           13 import javax.management.modelmbean.ModelMBeanAttributeInfo;
           14 import javax.management.modelmbean.ModelMBeanConstructorInfo;
           15 import javax.management.modelmbean.ModelMBeanInfo;
           16 import javax.management.modelmbean.ModelMBeanInfoSupport;
           17 import javax.management.modelmbean.ModelMBeanOperationInfo;
           18 import javax.management.modelmbean.RequiredModelMBean;
           19 
           20 public class HelloWorldModelMBean extends RequiredModelMBean {
           21     
           22     public HelloWorldModelMBean() throws Exception{}
           23     
           24     public static RequiredModelMBean createModelBean()
           25             throws RuntimeOperationsException, MBeanException,
           26             InstanceNotFoundException, InvalidTargetObjectTypeException {
           27         // 模型MBean信息
           28         ModelMBeanInfo info = buildModelMBeanInfo();
           29         // 模型MBean
           30         RequiredModelMBean modelMBean = new RequiredModelMBean(info);
           31         //目前只支持ObjectReference,將來可能會支持ObjectReference", "Handle", "IOR", "EJBHandle",
           32          //         or "RMIReference,
           33         //RMIReference從名字上可以看出,如果支持的話,那么以后就可以支持遠程MBean引用
           34         modelMBean.setManagedResource(new HelloWorld(), "ObjectReference");
           35         return modelMBean;
           36     }
           37 
           38     protected static ModelMBeanInfo buildModelMBeanInfo() throws RuntimeOperationsException, MBeanException {  
           39         // --  
           40         // attributes  
           41         // ------------------------------------------------------------------  
           42         ModelMBeanAttributeInfo[] attributes = new ModelMBeanAttributeInfo[1];  
           43   
           44         // 設置屬性
           45         Descriptor nameDesc = new DescriptorSupport();  
           46         nameDesc.setField("name", "hello");
           47         nameDesc.setField("value", "----dfdf---");
           48         nameDesc.setField("displayName", "myname");  
           49         nameDesc.setField("setMethod", "setHello");  
           50         nameDesc.setField("getMethod", "getHello");  
           51         nameDesc.setField("descriptorType", "attribute"); 
           52         attributes[0] = new ModelMBeanAttributeInfo("hello", "java.lang.String",  
           53                 "name say hello to", truetruefalse, nameDesc);  
           54   
           55         // --  
           56         // operations  
           57         // -------------------------------------------------------------------  
           58         ModelMBeanOperationInfo[] operations = new ModelMBeanOperationInfo[2];  
           59         String className = HelloWorld.class.getName();  
           60   
           61         // getName method  
           62         Descriptor getDesc = new DescriptorSupport(new String[] {  
           63                 "name=getHello", "descriptorType=operation",  
           64                 "class=" + className, "role=operation" });  
           65         operations[0] = new ModelMBeanOperationInfo("getHello", "get hello  ",  
           66                 nullnull, MBeanOperationInfo.ACTION,  getDesc);  
           67        
           68         Descriptor setDesc = new DescriptorSupport(new String[] {  
           69                 "name=setHello", "descriptorType=operation", 
           70                 "class=" + className, "role=operation" });  
           71         operations[1] = new ModelMBeanOperationInfo("setHello", "set hello  ",  
           72                 new MBeanParameterInfo[]{new MBeanParameterInfo("a","java.lang.String"," a method's arg ")},
           73                 null, MBeanOperationInfo.ACTION,  setDesc);  
           74   
           75         // constructors  
           76         ModelMBeanConstructorInfo[] constructors = new ModelMBeanConstructorInfo[1];  
           77         Constructor<?>[] ctors = HelloWorld.class.getConstructors();  
           78   
           79   
           80         constructors[0] = new ModelMBeanConstructorInfo("default constructor",  
           81                 ctors[0], null);  
           82   
           83         // ModelMBeanInfo  
           84         ModelMBeanInfo mmbeanInfo = new ModelMBeanInfoSupport(className,  
           85                 "Simple implementation of model bean.", attributes, null,  
           86                 operations/*null*/nullnull);  
           87         
           88         //設置一個Descriptor策略,這樣RequiredModelMBean改變 Attribute值得時候會記錄日志
           89         //當然RequiredModelMBean還需要addAttributeChangeNotificationListener,注冊一個監聽器
           90         Descriptor globalDescriptor = new DescriptorSupport(new String[]{
           91                 "name=HelloWorldModelMBean","displayName=globaldescriptor",
           92                 "descriptorType=mbean","log=T","logfile=hello.log"
           93         });
           94         mmbeanInfo.setMBeanDescriptor(globalDescriptor);
           95         
           96         return mmbeanInfo;  
           97     }  
           98 
           99 }
          100 

          使用ModelMBean中,有兩步很重要,第一步設置動態MBean元數據:setModelMBeanInfo(...),MBeanServer會利用這些元數據管理MBean。第二步設置ModelMBean需要管理的對象:setManagerdResourece(...),第一步的元數據其實也就是被管理對象的元數據。這二步都是可以在運行時候動態的配置的,對于ModelMBeanInfo和Resource等相關信息可以在xml文件中進行配置。所以對于ModelMBean的實現,可以很好的利用xml等工具。

          測試此MBean請看JmxTest類中的test3RequiredModelMBean()方法。  

          代碼:RequiredModelMBean.setAttribute(...)的執行分析
           1 JmxMBeanServer:
           2     public void setAttribute(ObjectName name, Attribute attribute)
           3         throws InstanceNotFoundException, AttributeNotFoundException,
           4                InvalidAttributeValueException, MBeanException,
           5                ReflectionException  {
           6 
           7         mbsInterceptor.setAttribute(cloneObjectName(name),
           8                                     cloneAttribute(attribute));
           9     }
          10 
          11 DefaultMBeanServerInterceptor:
          12     public void setAttribute(ObjectName name, Attribute attribute)
          13         throws InstanceNotFoundException, AttributeNotFoundException,
          14                InvalidAttributeValueException, MBeanException,
          15                ReflectionException  {
          16 .
          17         //得到動態MBean
          18         DynamicMBean instance = getMBean(name);
          19         instance.setAttribute(attribute);
          20 .
          21     }
          22 
          23 RequiredModelMBean:
          24     public void setAttribute(Attribute attribute)
          25         throws AttributeNotFoundException, InvalidAttributeValueException,
          26                MBeanException, ReflectionException 
          27 .
          28        //modelMBeanInfo就是最開始創建的信息,得到一個AttributeInfo
          29         ModelMBeanAttributeInfo attrInfo =
          30             modelMBeanInfo.getAttribute(attrName);
          31 .
          32         Descriptor mmbDesc = modelMBeanInfo.getMBeanDescriptor();
          33         Descriptor attrDescr = attrInfo.getDescriptor();
          34 .
          35             //得到set方法名
          36             String attrSetMethod = (String)
          37                 (attrDescr.getFieldValue("setMethod"));
          38             //得到get方法名
          39             String attrGetMethod = (String)
          40                 (attrDescr.getFieldValue("getMethod"));
          41 .
          42             //更具必要參數,執行set方法。改變被管理資源的值
          43                 invoke(attrSetMethod,
          44                        (new Object[] {attrValue}),
          45                        (new String[] {attrType}) );
          46 .
          47             //發出Attribute改變的事件
          48             sendAttributeChangeNotification(oldAttr,attribute);
          49 
          50     }
          51     public void sendAttributeChangeNotification(AttributeChangeNotification
          52                                                 ntfyObj)
          53         throws MBeanException, RuntimeOperationsException {
          54 .
          55         // log notification if specified in descriptor
          56         Descriptor ntfyDesc =
          57             modelMBeanInfo.getDescriptor(ntfyObj.getType(),"notification");
          58         //這個就是在例子中設置的globalDescriptor
          59         Descriptor mmbDesc = modelMBeanInfo.getMBeanDescriptor();
          60 .
          61  if (mmbDesc != null) {
          62             //這些值都是我們設置在globalDescriptor的策略,也就是具體                              //需要JMX的實現這需要各自實現的策略
          63             logging = (String) mmbDesc.getFieldValue("log");
          64             if ((logging != null) &&
          65                 ( logging.equalsIgnoreCase("t") ||
          66                   logging.equalsIgnoreCase("true") )) {
          67                 logfile = (String) mmbDesc.getFieldValue("logfile");
          68 
          69                 if (logfile != null) {
          70                     try {
          71                        //把相關信息寫入日志
          72                         writeToLog(logfile,"LogMsg: " +
          73                            ((new Date(ntfyObj.getTimeStamp())).toString())+
          74                            " " + ntfyObj.getType() + " " +
          75                            ntfyObj.getMessage() +
          76                            " Name = " + ntfyObj.getAttributeName() +
          77                            " Old value = " + oldv +
          78                            " New value = " + newv);
          79                     }
          80 
          81     }
          82 

          在ModelMBean中一些重要的類:
          ModelMBean:
          實現了DynamicMBean,說明了ModelMBean也是動態MBean的一類,PersistentMBean持久化功能接口,還實現了消息機制。
          圖:ModelMBean的結構圖


          ModelMBeanInfo、ModelMBeanAttributeInfo、ModelMBeanConstructorInfo、ModelMBeanNotificationInfo、ModelMBeanOperationInfo:
          這些類跟DynamicMBean里面介紹的類很相似,這里的ModelXXX都是XXX的子類。而且構成也跟他們的父類是一樣的,子類只是擴展了一些信息。

          RequiredModelMBean:
          RequiredModelMBean實現了ModelMBean其實實現了DynamicMBean,其實它也是一個動態的MBean,規范中說明對于使用ModelMBean,第三方供應商都必須實現RequiredMoelMBean。 

          參考:
          http://www.ibm.com/developerworks/cn/java/j-lo-jse63/index.html(Java SE 6 新特性: JMX 與系統管理)

          posted on 2012-09-24 08:33 heavensay 閱讀(6993) 評論(0)  編輯  收藏 所屬分類: JMX


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 成都市| 安乡县| 台江县| 周口市| 瑞丽市| 甘洛县| 蒙城县| 仙桃市| 芮城县| 光山县| 都兰县| 龙陵县| 礼泉县| 阳高县| 胶州市| 大田县| 济宁市| 香格里拉县| 呼和浩特市| 新和县| 黔南| 蛟河市| 额尔古纳市| 姜堰市| 阿拉善左旗| 盐津县| 镇江市| 永胜县| 永清县| 荃湾区| 云梦县| 西贡区| 长汀县| 郯城县| 济阳县| 婺源县| 平昌县| 巧家县| 彩票| 喀喇| 克东县|