淺談JMX

JMX在Java編程語言中定義了應用程序以及網絡管理和監控的 體系結構、設計模式、 應用程序接口以及服務。一般使用JMX來 監控系統的運行狀態或管理系統的某些方面,好比清空緩存、從新加載配置文件等
優勢是能夠很是容易的使應用程序被管理
伸縮性的架構使每一個JMX Agent服務能夠很容易的放入到Agent中,每一個JMX的實現都提供幾個核心的Agent服務,你也能夠本身編寫服務,服務能夠很容易的部署,取消部署。
主要做用是提供接口,容許有不一樣的實現。
  若是一個java對象能夠由一個遵循JMX規範的管理器應用程序管理,那麼這個java對象稱爲一個可由JMX管理的資源。實際上一個可由JMX管理的資源能夠是一個應用程序、一種實現、一個服務、一個設備、一個用戶等,一個可由JMX管理的資源也是由java編寫。並提供了一個相應的java包裝。
  若要使一個java對象成爲一個可由JMX管理的資源,則必須建立一個名爲Managed Bean或者 MBean的對象,MBean會提供它所管理的一些java對象的屬性和方法供管理應用程序使用,管理應用程序自己並不能直接訪問託管的java對象,所以,須要選擇託管的java對象的那些屬性能夠由管理應用程序使用。
  當擁有了一個MBean類以後,須要將其實例化,並將其註冊到另外一個做爲MBean服務器的java對象中,MBean服務器中保存了應用程序中註冊的全部MBean,管理應用程序經過MBean服務器來訪問MBean實例,能夠將JMX與Servlet應用程序作一個類比,管理應用程序的做用相似於Web瀏覽器,MBean服務器 的做用相似於Servlet容器,MBean服務器提供了使管理應用程序能夠訪問託管資源的方法。MBean實例就比如Servlet類或者Jsp頁面,Web瀏覽器沒法直接訪問servlet實例或JSP頁面,必需要經過Servlet容器才能夠,管理應用程序也必需要經過MBean服務器來訪問MBean實例。
  共有四種類型的MBean,分別爲標準類型、動態類型、開放類型、和模型類型,其中標準類型的MBean最容易編寫,可是靈活性最低,其餘三種類型的靈活性較好,其中咱們對模型MBean感興趣,由於Catalina中就使用了這種類型的MBean。
  從結構上將,JMX規範分爲三層:設備層、代理層和分佈式服務層,MBean服務器位於代理層,MBean位於設備層,分佈式服務層會在JMX規範未來的版本中涉及。
  設備層規範定義了編寫可由JMX管理的資源的標準,即如何編寫MBean,代理層定義了建立代理的規範,代理封裝了MBean服務器,提供了處理MBean的服務。代理和它所管理的MBean一般都位於同一個java虛擬機中,因爲JMX規範附帶了一個參考實現,所以並不須要本身編寫MBean服務器。

  MBeanServer類

  MBean服務器是javax.management.MBeanServer接口的實例,要建立一個MBeanServer實例。只須要調用javax.management.MBeanServerFactory類的createMBean()方法便可。html

  要將一個MBean註冊到MBean服務器中,能夠調用MBeanServer實例的registerMBean()方法,下面是registerMBean方法的簽名;java

ObjectInstance registerMBean(java.lang.Object object, ObjectName var2)
            throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException;

要調用registerMBean方法,須要傳入一個待註冊的MBean實例(就是第一個參數)和一個ObjectName實例,ObjectName實例與HashMap中的鍵相似,它能夠惟一地標識一個MBean實例。registerMBean方法會返回一個ObjectInstance實例。javax.management.ObjectInstance類封裝了一個MBean實例的對象名稱和它的類名。程序員

  要想獲取MBean實例或匹配某個模式的一組MBean實例。可使用MBeanServer接口提供的兩個方法,分別是queryNames方法 和 queryMBeans方法,queryNames方法返回一個java.util.Set實例,其中包含了匹配某個指定模式對象名稱的一組MBean實例的對象名稱,下面是queryNames方法的簽名:apache

java.util.Set queryNames(ObjectName name, QueryExp query);

其中 query制定了過濾條件,若參數name爲null 或者沒有域,並且指定了key屬性,name返回應註冊的MBean實例的全部ObjectName實例,若是參數query爲null,則不會對查找對象進行過濾。編程

  queryMBeans方法與queryNames方法相似,它返回的也是一個java.util.Set實例,可是其中包含的是被選擇的Mbean實例的ObjectInstance對象,queryMBean方法的簽名以下:設計模式

java.util.Set queryMBeans(ObjectName name, QueryExp query);

  一旦得到了所須要MBean實例對象名稱,就能夠操做託管資源在MBean實例中提供的屬性或調用其方法,數組

  能夠經過調用MBeanServer接口的invoke方法調用已經註冊的MBean實例的任何方法,MBeanServer接口的getAttribute方法 和 setAttribut方法用於獲取或設置已經註冊的MBean實例的屬性。瀏覽器

ObjectName類

  MBean實例註冊於MBean服務器中,MBean服務器中的每個MBean實例都經過一個對象名稱來惟一標識,就好像是HashMap中的每個條目都經過一個鍵來惟一的標識同樣。緩存

  對象名稱是javax.managerment.ObjectName類的實例,對象名稱由兩部分組成,域和一個鍵/值對。域是一個字符串,也能夠是空字符串,在對象名稱中,域後接一個分號,而後是一個或者多個鍵/值對,在鍵/值對重,鍵(key)是一個非空字符串,而且不能包含下列字符:等號、逗號、分號、星號、和問號。在一個對象名稱中,同一個鍵只能出現一次,服務器

  鍵與其值是由等號分隔的,鍵/值對之間用逗號號分隔。例以下面是一個有效的對象名稱,其中包含兩個鍵:

myDomain:type=Car,color=blue
域:key=value,key = value

ObjetName實例也表示在MBean服務器中搜索MBean實例的屬性模式,ObjectName實例能夠在 域 部分或者 鍵值對 部分使用通配符來表示模式,做爲模式的ObjectName能夠有 0 個或多個鍵。

標準MBean

  標準MBean是最簡單的MBean類型,要想經過標準MBean來管理一個java對象,須要執行如下步驟。

  1. 建立一個接口,該接口的命名規範爲:java類名+MBean後綴。例如,若是想要管理的java類名爲Car,則須要建立的接口命名爲CarMBean;
  2. 修改java類,讓其實現剛剛建立的CarMBean接口。
  3. 建立一個代理,該代理類必須包含一個MbeanServer實例。
  4. 爲Mbean建立ObjectName實例;
  5. 實例化MBeanServer類,
  6. 將MBean註冊到MBeanServer中;

  標準MBean是最容易編寫的MBean類型,可是用標準MBean就必需要修改原有的java類,在某些項目中,這不是問題,可是在其餘一些項目(尤爲是不少類的項目)中,這是不能夠接受的,其餘類型的MBean容許在不修改原有java類的基礎上管理java對象,

下面是一個標準MBean的例子,其中假設你想要使其成爲JMC可管理的類是Car,

第一步 先建立一個符合命名規範的接口

 1 package myex20.pyrmont.Standardmbeantest;
 2 
 3 /**
 4  * <p>
 5  * <b>Title:CarMBean.java</b>
 6  * </p>
 7  * <p>
 8  * Copyright:ChenDong 2018
 9  * </p>
10  * <p>
11  * Company:僅學習時使用
12  * </p>
13  * <p>
14  * 類功能描述:要管理Car類的標準MBean接口
15  * 建立一個接口,該接口的命名規範爲:java類名+MBean後綴。例如,若是想要管理的java類名爲Car,則須要建立的接口命名爲CarMBean;
16  * </p>
17  * <p>
18  * 基本上來說,要在接口中聲明Car類中的所要提供的全部方法,在這個例子中,在CarMBean接口中生命了Car類的全部方法,若是不但願Car類的drive方法在管理應用程序中調用,
19  * 只須要將drive方法的定義從CarMBean中移除便可。
20  * </p>
21  * 
22  * @author 陳東
23  * @date 2018年12月4日 下午7:36:50
24  * @version 1.0
25  */
26 public interface CarMBean {
27     public String getColor();
28 
29     public void setColor(String color);
30 
31     public void drive();
32 
33 }

而後讓咱們想要被管理的原java類 也就是 Car類實現該接口

 1 package myex20.pyrmont.Standardmbeantest;
 2 
 3 /**
 4  * <p>
 5  * <b>Title:Car.java</b>
 6  * </p>
 7  * <p>
 8  * Copyright:ChenDong 2018
 9  * </p>
10  * <p>
11  * Company:僅學習時使用
12  * </p>
13  * <p>
14  * 類功能描述:
15  * </p>
16  * 
17  * @author 陳東
18  * @date 2018年12月4日 下午7:34:25
19  * @version 1.0
20  */
21 public class Car implements CarMBean {
22     private String color = "red";
23 
24     public String getColor() {
25         return color;
26     }
27 
28     public void setColor(String color) {
29         this.color = color;
30     }
31 
32     public void drive() {
33         System.out.println("Baby you can drive my*" + color + "*car.");
34     }
35 }

而後建立一個代理類 包含一個 MBeanServer類的實例 來管理 Mbean

  1 package myex20.pyrmont.Standardmbeantest;
  2 
  3 import javax.management.Attribute;
  4 import javax.management.AttributeNotFoundException;
  5 import javax.management.InstanceAlreadyExistsException;
  6 import javax.management.InstanceNotFoundException;
  7 import javax.management.InvalidAttributeValueException;
  8 import javax.management.MBeanException;
  9 import javax.management.MBeanRegistrationException;
 10 import javax.management.MBeanServer;
 11 import javax.management.MBeanServerFactory;
 12 import javax.management.NotCompliantMBeanException;
 13 import javax.management.ObjectName;
 14 import javax.management.ReflectionException;
 15 
 16 /**
 17  * <p>
 18  * <b>Title:StandardAgent.java</b>
 19  * </p>
 20  * <p>
 21  * Copyright:ChenDong 2018
 22  * </p>
 23  * <p>
 24  * Company:僅學習時使用
 25  * </p>
 26  * <p>
 27  * 類功能描述: 代理類用來實例化MBean服務器,並使用MBean服務器註冊CarBean實例。首先要注意的是變量
 28  * MBeanServer,StandardAgent類的構造函數會將一個MBeanServer實例賦值給變量MBeanServer。
 29  * 構造函數會調用MBeanServerFactory類的createMBeanServer方法 建立一個MBeanServer實例,
 30  * createMBeanServer方法
 31  * 會返回JMX參考實現的一個默認的MBeanServer對象。資深JMX程序員可能會實現本身的MBeanServer,
 32  * </p>
 33  * * @author 陳東
 34  * 
 35  * @date 2018年12月4日 下午7:44:13
 36  * @version 1.0
 37  */
 38 public class StandardAgent {
 39     /**
 40      * 管理MBean的服務器實例
 41      */
 42     private MBeanServer mBeanServer = null;
 43 
 44     /**
 45      * 
 46      * 
 47      * <p>
 48      * Title:無參數構造器
 49      * </p>
 50      * 
 51      * <p>
 52      * Description: 使用默認構造建立一個新的{@code StandardAgent }實例
 53      * </p>
 54      */
 55     public StandardAgent() {
 56         // 使用MBeanServerFactory工程類 建立MBeanServer實例
 57         mBeanServer = MBeanServerFactory.createMBeanServer();
 58     }
 59 
 60     /**
 61      * 
 62      * 
 63      * <p>
 64      * Title: getMBeanServer
 65      * </p>
 66      * 
 67      * @date 2018年12月4日 下午7:51:31
 68      * 
 69      *       <p>
 70      *       功能描述: 獲取代理類中的MBeanServer實例
 71      *       </p>
 72      * 
 73      * @return
 74      */
 75     public MBeanServer getMBeanServer() {
 76         return mBeanServer;
 77     }
 78 
 79     /**
 80      * 
 81      * 
 82      * <p>
 83      * Title: createObjectName
 84      * </p>
 85      * 
 86      * @date 2018年12月4日 下午7:55:07
 87      * 
 88      *       <p>
 89      *       功能描述: 根據指定的name屬性來建立 {@code ObjectName} 實例
 90      *       </p>
 91      * 
 92      * @param name
 93      * @return
 94      */
 95     public ObjectName createObjectName(String name) {
 96         ObjectName objectName = null;
 97         try {
 98             objectName = new ObjectName(name);
 99         } catch (Exception e) {
100             e.printStackTrace();
101         }
102         return objectName;
103 
104     }
105 
106     /**
107      * 
108      * 
109      * <p>
110      * Title: createStandardBean
111      * </p>
112      * 
113      * @date 2018年12月4日 下午8:09:01
114      *       <p>
115      *       功能描述: 方法中會調用MBeanServer實例的createMBean方法,createMBean方法接收託管資源的類名,
116      *       和一個ObjectName實例,該ObjectName實例
117      *       惟一的表示了爲託管資源建立的MBean實例,creatMBean方法也會將建立的MBean實例註冊到MBean
118      *       服務器中。因爲標準MBean實例遵循了特定的命名規則,所以不須要
119      *       爲createMbean方法提供MBean的類名,若是託管資源的類名是Car,則建立的MBean的類名爲CarMBean。
120      *       </p>
121      * 
122      * 
123      * @param objectName
124      * @param managedResourceClassName
125      */
126     @SuppressWarnings("unused")
127     private void createStandardBean(ObjectName objectName, String managedResourceClassName) {
128         try {
129             mBeanServer.createMBean(managedResourceClassName, objectName);
130         } catch (InstanceAlreadyExistsException e) {
131             // TODO Auto-generated catch block
132             e.printStackTrace();
133         } catch (NotCompliantMBeanException e) {
134             // TODO Auto-generated catch block
135             e.printStackTrace();
136         } catch (MBeanRegistrationException e) {
137             // TODO Auto-generated catch block
138             e.printStackTrace();
139         } catch (MBeanException e) {
140             // TODO Auto-generated catch block
141             e.printStackTrace();
142         } catch (ReflectionException e) {
143             // TODO Auto-generated catch block
144             e.printStackTrace();
145         }
146 
147     }
148 
149     public static void main(String[] args) {
150         // 建立一個代理類的實例
151         StandardAgent agent = new StandardAgent();
152         // 獲取一個MBeanServer 的引用
153         MBeanServer mBeanServer = agent.getMBeanServer();
154 
155         /**
156          * 爲咱們要管理的CarBean實例
157          * 建立一個ObjectName對象,MBeanServer實例的默認域會做爲ObjectName實例的域使用。
158          * 一個名爲type的鍵會被添加到域的後面,鍵type的值是託管資源的徹底限定名;
159          */
160         // 獲取 MBeanServer實例的默認域
161         String domain = mBeanServer.getDefaultDomain();
162         // 被託管資源java類的徹底限定名 不是對應的MBean包裝類
163         String managedResourceClassName = "myex20.pyrmont.Standardmbeantest.Car";
164         // 而後建立ObjectName對象
165         ObjectName oname = agent.createObjectName(domain + ":type=" + managedResourceClassName);
166         // 調用 agent的 createStandardMBean方法,並傳入建立好的 對象名稱對象 和 託管資源java類的 類限定名
167         // 接着 就會調用MBeanServer的 creatMBean來建立並管理
168         // CarMBean,也就是經過CarMBean實例來管理Car對象。
169         agent.createStandardBean(oname, managedResourceClassName);
170         // 建立一個名爲 colorattribute的Attribute類型的對象,用來表示Car類的color屬性,並設置其值 爲blue,
171         Attribute colorattribute = new Attribute("Color", "blue");
172         // 而後 用MBean 服務器對象的setAttribute方法,傳入表明 CarMBean 的ObjectName 對象 與 爲
173         // CarBean管理的Car設置的Attitude對象
174         try {
175             mBeanServer.setAttribute(oname, colorattribute);
176             System.out.println(mBeanServer.getAttribute(oname, "Color"));
177             mBeanServer.invoke(oname, "drive", null, null);
178         } catch (InstanceNotFoundException | InvalidAttributeValueException | AttributeNotFoundException
179                 | ReflectionException | MBeanException e) {
180 
181             e.printStackTrace();
182         }
183 
184     }
185 
186 }

剩餘步驟你們看 上面代碼吧 ,不想再寫啦哈。

從上面的例子咱們能夠看到,咱們已經能夠經過StandardAgent類來直接訪問Car對象了,可是這裏的關鍵問題是能夠選擇那些功能要暴露出來,那些方法須要對外隱藏。

模型MBean

  相對於標準MBean,模型MBean更具備靈活性,在編程上,模型MBean難度更大一些,可是也不須要爲可管理的對象修改原java類了,若是不能修改已有的java類,那麼使用模型MBean是一個不錯的選擇。

  使用模型MBean與使用標準MBean有一些區別,在使用標準MBean來管理資源時,須要定義一個接口,而後讓託管資源實現該接口,而使用模型MBean時,不須要定義接口,相反是可使用javax.management.modelmbean.ModelMBean接口來表示模型MBean

,只須要實現該接口,在JMX的參考實現中,有一個javax.management.modelmbean.RequiredModelMBean類,是ModelMBean接口的默認實現,能夠實例化RequiredModelMBean類或者其子類,也可使用ModelMBean接口的其餘實現類。

 編寫一個模型MBean的最大挑戰是告訴ModelMBean對象託管資源的那些屬性和方法能夠暴露給代理,能夠經過建立 javax.management,modelmbean.ModelMBeanInfo對象來完成這個任務,ModelMBeanInfo對象描述了將會暴露給代理的構造函數、屬性、操做、甚至是監聽器。建立ModelMBeanInfo對象是一件特別枯燥的事情,但當建立了該實例後,只須要將其與ModelMBean對象相關聯便可。

 使用RequiredModelMBean類做爲ModelMBean的實現,有兩種方式能夠將ModelMBeanInfo對象相關聯;

  1. 傳入一個ModelMBeanInfo對象到 RequiredModelMBean對象的構造函數中
  2. 調用RequiredModelMBean類的setModelMBeanInfo方法,並傳入一個ModelMBean對象

  在建立了ModelMBean對象以後,須要調用ModelMbean接口的setManagedResource方法將 ModelMBean與其託管的資源相互關聯,該方法的簽名以下

public void setManagedResource(java.lang.Object managedResource, java.lang.String managedResourceType) throws MBeanException, RuntimeOperationsException, InstanceNotFoundException, InvalidTargetObjectTypeException ;

字符串參數 managedResourceType的值只能夠是下面之一:ObjectReference、Handle、IOR、EJBHandle或者RMIReference。當前只支持ObjectReference。

  還須要建立一個ObjectName實例,並將MBean實例註冊到MBean服務器中,下面先介紹一下ModelMBeanInfo接口,該接口的實例會將託管資源的屬性 和方法提供給代理層。

MBeanInfo 接口 與 ModelMBeanInfo接口

  javax.management,mbean.ModelMBeanInfo接口描述了要經過ModelMBean暴露給代理層的構造函數、屬性、方法、和監聽器,其中 構造函數是  javax.management.modelmbean.ModelMBeanConstructorInfo類的實例,屬性是javax.management.modelmbean.ModelMBeanAttributeInfo類的實例,方法是javax.management.modelmbean.ModelMBeanOperationInfo類的實例,監聽器是 javax.management.modelmbean.ModelMBeanNotificationInfo類的實例,

  JMX提供了ModelMBeanInfo接口的默認實現,即javax.management.modelmbean.ModelMBeanInfoSupport類。下面展現一下 咱們後面要使用的ModelMBeanInfoSupport類的構造函數:

public ModelMBeanInfoSupport(String className,
            String description,
            ModelMBeanAttributeInfo[] attributes,
            ModelMBeanConstructorInfo[] constructors,
            ModelMBeanOperationInfo[] operations,
            ModelMBeanNotificationInfo[] notifications) {
        this(className, description, attributes, constructors,
                operations, notifications, null);
    }

 

 

能夠經過調用ModelMBeanAttributeInfo類的構造函數來建立ModelMBeanAttributeInfo對象:

 public ModelMBeanAttributeInfo(String name,
                                       String type,
                                       String description,
                                       boolean isReadable,
                                       boolean isWritable,
                                       boolean isIs,
                                       Descriptor descriptor)

下面是參數列表:

  • name:屬性的名稱
  • type,屬性的類型名
  • description:對屬性的描述
  • isReadable:,true表示針對該屬性有一個getter方法,false表示沒有
  • isWriteable:true 表示針對該屬性有一個 setter方法,false表示沒有
  • isIs,true 表示針對該屬性有一個getter方法 ,false表示沒有
  • descriptor:Descriptor類的實例,包含Attribute的適當元數據,若是它爲null,會建立默認的Descriptor實例。

可使用下面的構造函數建立一個 ModelMBeanOperationInfo對象

 public ModelMBeanOperationInfo(String name,
                                       String description,
                                       MBeanParameterInfo[] signature,
                                       String type,
                                       int impact,
                                       Descriptor descriptor)

下面是參數列表;

  • name:方法名
  • description :方法描述
  • signature:MBeanParameterInfo對象的數組,描述了方法的參數
  • type:方法的返回值類型
  • impact:方法的影響 是一個整型變量 ,爲了方便你們的使用 使用了javax.management.MBeanOperationInfo類中的幾種常量來表示   
  1.     /**
         * 方法返回信息但不改變任何狀態
         */
        public static final int INFO = 0;

     

  2.  /**
         *    指示該操做是寫式的:它具備效果,但不從MBean返回任何信息
         */
        public static final int ACTION = 1;

     

  3.  /**
         *指示該操做既讀又寫:它具備效果,而且還返回來自MBean的信息
         */
        public static final int ACTION_INFO = 2;

     

  4.  /**
         * 指示操做的影響是未知的,或者沒法使用其餘值之一來表示。
         */
        public static final int UNKNOWN = 3;

    只能夠選擇上面的四種

  • descriptor:Descriptor實例,包含MBeanOperationInfo實例的適當元數據

 咱們仍是使用原來的Car類做爲MBean的管理對象代碼以下

package myex20.pyrmont.Standardmbeantest;

/**
 * <p>
 * <b>Title:Car.java</b>
 * </p>
 * <p>
 * Copyright:ChenDong 2018
 * </p>
 * <p>
 * Company:僅學習時使用
 * </p>
 * <p>
 * 類功能描述:
 * </p>
 * 
 * @author 陳東
 * @date 2018年12月4日 下午7:34:25
 * @version 1.0
 */
public class Car {
    private String color = "red";

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public void drive() {
        System.out.println("Baby you can drive my*" + color + "*car.");
    }
}

對於模型MBean,不須要像使用標準MBean那樣,編寫一個接口,只須要實例化RequiredMBean類,下面展現一個ModelAgent類的定義,該類用來建立模型MBean實例,並管理Car對象。

 

  1 package myex20.pyrmont.modelmbeantest1;
  2 
  3 import javax.management.Attribute;
  4 import javax.management.AttributeNotFoundException;
  5 import javax.management.Descriptor;
  6 import javax.management.InstanceNotFoundException;
  7 import javax.management.InvalidAttributeValueException;
  8 import javax.management.MBeanException;
  9 import javax.management.MBeanInfo;
 10 import javax.management.MBeanOperationInfo;
 11 import javax.management.MBeanParameterInfo;
 12 import javax.management.MBeanServer;
 13 import javax.management.MBeanServerFactory;
 14 import javax.management.MalformedObjectNameException;
 15 import javax.management.ObjectName;
 16 import javax.management.ReflectionException;
 17 import javax.management.RuntimeOperationsException;
 18 import javax.management.modelmbean.DescriptorSupport;
 19 import javax.management.modelmbean.InvalidTargetObjectTypeException;
 20 import javax.management.modelmbean.ModelMBean;
 21 import javax.management.modelmbean.ModelMBeanAttributeInfo;
 22 import javax.management.modelmbean.ModelMBeanInfo;
 23 import javax.management.modelmbean.ModelMBeanInfoSupport;
 24 import javax.management.modelmbean.ModelMBeanOperationInfo;
 25 import javax.management.modelmbean.RequiredModelMBean;
 26 
 27 /**
 28  * <p>
 29  * <b>Title:ModelAgent.java</b>
 30  * </p>
 31  * <p>
 32  * Copyright:ChenDong 2018
 33  * </p>
 34  * <p>
 35  * Company:僅學習時使用
 36  * </p>
 37  * <p>
 38  * 類功能描述:用於建立模型MBean的實例,在該類中用其JMX參考中的默認實現RequiredModelMBean,並管理Car
 39  * 幷包含一個MBeanServer實例
 40  * 
 41  * </p>
 42  * <p>
 43  * 請訪問下面網址 進行 參考學習 {@see https://www.cnblogs.com/ChenD/p/10061598.html}
 44  * </p>
 45  * 
 46  * @author 陳東
 47  * @date 2018年12月5日 下午9:24:36
 48  * @version 1.0
 49  */
 50 public class ModelAgent {
 51     /**
 52      * 管理的Car類的徹底限定名
 53      */
 54     private String MANAGED_CLASS_NAME = "myex20.pyrmont.modelmbeantest1.Car";
 55 
 56     /**
 57      * 用於管理MBean的MBeanServer實例
 58      */
 59     private MBeanServer mBServer = null;
 60 
 61     public ModelAgent() {
 62         mBServer = MBeanServerFactory.createMBeanServer();
 63     }
 64 
 65     public MBeanServer getMBeanServer() {
 66         return mBServer;
 67     }
 68 
 69     /**
 70      * 
 71      * 
 72      * <p>
 73      * Title: createObjectName
 74      * </p>
 75      * 
 76      * @date 2018年12月5日 下午9:39:47
 77      * 
 78      *       <p>
 79      *       功能描述:用指定的name建立ObjectName對象
 80      *       </p>
 81      * 
 82      * @param name
 83      * @return
 84      */
 85     private ObjectName createObjectName(String name) {
 86         ObjectName obj = null;
 87 
 88         try {
 89             obj = new ObjectName(name);
 90         } catch (MalformedObjectNameException e) {
 91 
 92             e.printStackTrace();
 93         }
 94         return obj;
 95 
 96     }
 97 
 98     /**
 99      * 
100      * 
101      * <p>
102      * Title: createMBean
103      * </p>
104      * 
105      * @date 2018年12月6日 下午9:39:09
106      * 
107      *       <p>
108      *       功能描述:建立 ModelMBean
109      *       </p>
110      * 
111      * @param objectName
112      * @param mbeanName
113      * @return
114      */
115     private ModelMBean createMBean(ObjectName objectName, String mbeanName) {
116         // ModelMBeanInfo接口描述了要經過ModelMBean暴露給代理層的構造函數、屬性、方法、和監聽器
117         // 先建立一個描述 要建立的ModelMBean類 要暴露給代理層的 各類 信息
118         ModelMBeanInfo mBeanInfo = createModelMBeanInfo(objectName, mbeanName);
119         RequiredModelMBean modelMBean = null;
120         try {
121             modelMBean = new RequiredModelMBean(mBeanInfo);
122         } catch (Exception e) {
123             e.printStackTrace();
124         }
125         return modelMBean;
126     }
127 
128     /**
129      * 
130      * 
131      * <p>
132      * Title: createModelMBeanInfo
133      * </p>
134      * 
135      * @date 2018年12月5日 下午10:03:03
136      * 
137      *       <p>
138      *       功能描述:爲ModelMBean 類建立類信息 ModelMBeanInfo
139      * 
140      *       </p>
141      *       <p>
142      *       對象 ModelMBeanInfo對象的幾個子接口 構造函數是
143      *       javax.management.modelmbean.ModelMBeanConstructorInfo類的實例,
144      *       屬性是javax.
145      *       management.modelmbean.ModelMBeanAttributeInfo類的實例,方法是javax.
146      *       management.modelmbean.ModelMBeanOperationInfo類的實例,監聽器是
147      *       javax.management.modelmbean.ModelMBeanNotificationInfo類的實例,
148      *       </p>
149      * 
150      * @param inMBeanObjectName
151      * @param inMBeanName
152      * @return
153      */
154     private ModelMBeanInfo createModelMBeanInfo(ObjectName inMBeanObjectName, String inMBeanName) {
155 
156         // ModelMBean類的 類信息接口
157         ModelMBeanInfo mBeaninfo = null;
158         // ModelMBean類的 屬性 對象集合
159         ModelMBeanAttributeInfo[] attributes = new ModelMBeanAttributeInfo[1];
160         // ModelMBean類的 方法 對象集合
161         ModelMBeanOperationInfo[] operations = new ModelMBeanOperationInfo[3];
162         try {
163 
164             // 屬性名:Color,類型:java.lang.String 描述信息:the Color。 isReadable:true
165             // 有getter方法,isWriteable:true 有setter方法
166             // isIS :false 無getter方法,descriptor :無
167             attributes[0] = new ModelMBeanAttributeInfo("Color", "java.lang.String", "the Color.", true, true, false,
168                     null);
169             /**
170              * 第三個參數爲 該方法的參數數組 null表明無參數,
171              */
172             operations[0] = new ModelMBeanOperationInfo("drive", "the drive method", null, "void",
173                     MBeanOperationInfo.ACTION, null);
174             /**
175              * Car的getColor方法
176              * 
177              */
178             operations[1] = new ModelMBeanOperationInfo("getColor", "get color attribute", null, "java.lang.String",
179                     MBeanOperationInfo.ACTION, null);
180 
181             // setColor方法
182             String fileds[] = new String[] { "name=setColor", "descriptorType=operation", "class=" + MANAGED_CLASS_NAME,
183                     "role=operation" };
184             Descriptor setColorDesc = new DescriptorSupport(fileds);
185             /**
186              * MBeanOperationInfo 描述方法的參數對象
187              */
188             MBeanParameterInfo[] setColorParams = new MBeanParameterInfo[] {
189                     new MBeanParameterInfo("new color", "java.lang.String", "new Color value") };
190             /**
191              * name:方法名 description :方法描述
192              * signature:MBeanParameterInfo對象的數組,描述了方法的參數 type:方法的返回值類型
193              * impact:方法的影響 是一個整型變量 ,爲了方便你們的使用
194              * 使用了javax.management.MBeanOperationInfo類中的幾種常量來表示
195              * ACTION:指示該操做是寫式的:它具備效果,但不從MBean返回任何信息
196              */
197 
198             operations[2] = new ModelMBeanOperationInfo("setColor", "set color attribute", setColorParams, "void",
199                     MBeanOperationInfo.ACTION, setColorDesc);
200 
201             mBeaninfo = new ModelMBeanInfoSupport(MANAGED_CLASS_NAME, null, attributes, null, operations, null);
202 
203         } catch (Exception e) {
204             e.printStackTrace();
205         }
206         return mBeaninfo;
207 
208     }
209 
210     public static void main(String[] args) {
211 
212         ModelAgent agent = new ModelAgent();
213         MBeanServer server = agent.getMBeanServer();
214         Car car = new Car();
215         // 獲取 MBeanServer實例的默認域
216         String domain = server.getDefaultDomain();
217         ObjectName objectName = agent.createObjectName((domain + ":type=MyCar"));
218         String mbeanName = "myMBean";
219         ModelMBean bean = agent.createMBean(objectName, mbeanName);
220         // 在建立了ModelMBean對象以後,須要調用ModelMbean接口的setManagedResource方法將
221         // ModelMBean與其託管的資源相互關聯,
222         // public void setManagedResource(java.lang.Object managedResource,
223         // java.lang.String managedResourceType) throws MBeanException,
224         // RuntimeOperationsException, InstanceNotFoundException,
225         // InvalidTargetObjectTypeException ;
226         // managedResourceType 目前只支持 ObjectReference
227         try {
228             bean.setManagedResource(car, "ObjectReference");
229             // 將與託管資源關聯好的ModelMBean 註冊到 MBean服務器中
230             server.registerMBean(bean, objectName);
231 
232         } catch (Exception e) {
233             // TODO Auto-generated catch block
234             e.printStackTrace();
235         }
236         // 管理代理類
237 
238         try {
239             Attribute attribute = new Attribute("Color", "green");
240             server.setAttribute(objectName, attribute);
241             String color = (String) server.getAttribute(objectName, "Color");
242             System.out.println("Color:" + color);
243 
244             attribute = new Attribute("Color", "blue");
245             server.setAttribute(objectName, attribute);
246             color = (String) server.getAttribute(objectName, "Color");
247             System.out.println("Color:" + color);
248             
249        251             server.invoke(objectName, "drive", null, null);
252             server.invoke(objectName, "setColor", new String[]{"blue"},new String[]{"java.lang.String"});
253             server.invoke(objectName, "drive", null, null);
254 
255         } catch (Exception e) {
256             // TODO Auto-generated catch block
257             e.printStackTrace();
258         }
259 
260     }
261 
262 }

在執行main以後 的運行結果

Color:green
Color:blue
Baby you can drive my*red*car.
Baby you can drive my*blue*car.

由於在使用MBeanServer類的invoke時  看下方法簽名吧 我一次傳帶參數的值 就傳錯了 記錄下

public Object invoke(ObjectName name, String operationName,
                         Object params[], String signature[])
            throws InstanceNotFoundException, MBeanException,
                   ReflectionException;
  • name: 註冊時 用的ObjectName對象
  • operationName:要調用的方法名
  • params:表明參數數組 定義成Object 是爲了能夠知足任何類型的參數 ,按照參數順序依次 定義數組內容
  • signature:也是一個數組 表明 參數 元素的 類型 例如 參數是String 那麼它的類型 就是 java.lang.String 

從上面的例子咱們已經看出來了 最麻煩的就是建立ModelMBeanInfo信息了,若是這個步驟不能夠簡化 那麼這個ModelMBean將不具有可用性,

那麼爲了簡化建立ModelMBeanInfo信息引入了一個Commons Modeler 庫

Commons Modeler

   Commons Modeler 庫是Apache軟件基金會的Jakarta項目的一部分,目的就是使編寫模型MBean更加方便,事實上最大的幫助是不須要向上面同樣寫建立ModelMBeanInfo對象的代碼了。

回憶下以前的例子,在建立RequiredModelMBean實例時,須要建立一個ModelMBeanInfo對象,並將其傳給RequiredModelMBean類的構造函數:

ModelMBeanInfo mBeanInfo = createModelMBeanInfo(objectName, mbeanName);
        RequiredModelMBean modelMBean = null;
        try {
            modelMBean = new RequiredModelMBean(mBeanInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }

ModelMbeanInfo對象描述了將要由MBean實例暴露出來的屬性和方法,實現createModelMBeanInfo方法是特別枯燥的並且麻煩死了,由於必須列出全部要暴露出來的屬性和方法 並將它們傳給ModelMBeanInfo對象。

  而使用Commons Modeler庫,就不在須要建立ModelMBeanInfo對象了,相反對模型MBean的描述被封裝在一個 org.apache.catalina.modeler.ManagedBean對象中。不須要編寫代碼在MBean中暴露出屬性和方法。只須要編寫一個mbean描述文件(一個XML文檔),列出想要建立的MBean,對於每一個MBean,須要寫出MBean類和託管資源類的徹底限定名,此外還有由MBean暴露出來的屬性和方法,而後使用org.apache.commons.modeler.Registry實例來讀取這個XML文檔,並建立一個MBeanServer實例,在按照mbean描述文件中的XML元素建立全部的ManagedBean實例。

  而後調用ManagedBean實例的createMBean方法建立模型MBean,這以後就是普通的流程了,須要建立ObjectName對象的實例,並將其與MBean實例一塊兒註冊到MBean服務器中,下面會先介紹一下mbean描述文件的格式,而後討論Modeler庫中的三個重要的類,分別是Registry類,ManagedBean類、和BaseModelMBean類。

注意:爲了更好的理解Modeler庫,org.apache.catalina.mbeans包中與MBean相關類的工做原理 。咱們仍然使用老版本,

 MBean描述符

  MBean描述符是一個XML 文檔,該文檔描述了將會由Mbean服務器管理的 ModelMBean的實例,MBean描述符如下面的頭信息開始:

<?xml version="1.0"?>
<!DOCTYPE mbeans-descriptors PUBLIC
"-//Apache Software Foundation//DTD Model MBeans Configuration File"
"http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd">

  接下來是mbeans-descriptors的根元素

<mbeans-descriptors>
...
</mbeans-descriptors>

  在開始和末尾的mbeans-descriptors標籤內部是mbean元素,每個mbean元素標籤表示一個模型MBean,mbean元素包含了分別用來表示屬性、方法、構造函數、和通知的元素。

mbean元素

  mbean元素描述了一個模型MBean,包含建立對應ModelMBeanInfo對象的信息。mbean元素的定義以下所示:

<!ELEMENT mbean(descriptor?,attribute*,constructor*,notification*,operation*)>

  mbean元素定義了具體的規範,mbean元素能夠有一個可選的descriptor元素,0個或者多個attribute元素。0個或者多個constructor元素,0個或者多個notification元素。0個或者多個operation元素。

  mbean元素能夠有以下的屬性:

  • className :實現ModelMBean接口的java類的徹底限定名,若該屬性未賦值,則默認使用org.apache.commons.modeler.BaseModelMBean類;
  • description: 該ModelMBean類的簡單描述
  • domain:在建立ModelMBean的ObjectName對象時,託管的bean 的 ModelMBean實例被註冊到MBeanServer的域名。
  • group: 組分類的可選名,能夠用來選擇具備類似MBean實例類的組;
  • name:惟一標識模型MBean的名稱,通常狀況下,會使用相關服務器組件的基類名。
  • type:託管資源實現類的徹底限定java類名。
attribute 元素

  使用attribute元素描述MBean的javaBean屬性。attribute元素有一個可選的descripotr元素,attribute元素能夠由以下的屬性:

  • description:該屬性的簡單描述
  • displayName:該屬性的顯示名稱;
  • getMethod:返回 attribute元素 的getter方法;
  • is:一個布爾值,指明該屬性是不是一個布爾值,是否有getter方法,默認狀況下,該屬性值爲false;
  • name:該javaBean屬性的名稱:
  • readable:一個布爾值,指明該屬性對管理應用程序來講是否可讀,該屬性默認值爲 true;
  • setMethod,設置 attribute屬性的setter方法;
  • type:該屬性的徹底限定java類名;
  • writeable:一個布爾值。指明該屬性對管理應用程序來講是否可寫,該屬性的默認值爲true;
operation 元素

  operation元素描述了模型MBean 中要暴露給管理應用程序的公共方法,它能夠有.個或者多個parameter子元素和以下的屬性:

  • description:方法的簡單描述
  • impact:指明方法的影響,可選值,ACTION、ACTION-INFO、INFO或UNKNOWN;值的意思參考  ModelMBeanOperationInfo對象 的講述;
  • name:公共方法的名稱;
  • returnType:方法返回值的徹底限定的java類名。
parameter 元素

  parameter元素描述了將要傳遞給構造函數 或者 方法的參數,它能夠有以下的屬性:

  • description:該參數的簡單描述
  • name:參數名
  • type:該參數徹底限定的java類名

mbean元素的示例

  在Catalin的 mbean-descriptors.xml文件中聲明瞭一系列模型MBean,該文件位於org.apache.catalina.mbean 包下,下面給出了 mbean-descriptors.xml文件中對於StandardServer MBean的聲明

<mbean name="StandardServer" className="org.apache.catalina.mbeans.StandardServerMBean"
description="Standard Server Component"
domain="Catalina"
group="Server"
type="org.apache.catalina.core.StandardServer">

<attribute name="debug"
description="The debugging detail level fot this component"
type="int"/>

<attribute name="managedResource"
description="The managed resource this MBean is asscoiated with"
type="java.lang.Object"/>

<attribute name="port"
description="TCP port for shutdown messages"
type="int"/>

<attribute name="shutdown"
description="Shutdown password"
type="java.lang.String"/>

<operation name="store" 
description="Save current state to server.xml file"
impact="ACTION"
returnType="void">
</operation>
</mbean>

上述代碼中的mbean元素聲明瞭一個模型MBean,其惟一標識是StandardServer,該MBean是org.apache.catalina.mbeans.StandardServerMBean類的一個對象,負責管理org.apache.catalina.core.StandardServer類的對象。

domain屬性的值是 Catalina,group的屬性是Server。

  模型MBean暴露出的屬性有四個,分別是debug、managedResource、port和shutdown。正如mbean元素中嵌套的四個attribute元素所描述的同樣,此外,Mbean還暴露出了一個方法,即 store方法,由 operation元素描述。

 

本身編寫一個模型MBean類

 使用Commons Modeler庫,須要在mbean元素的className屬性中指明自定義的模型MBean的類型,默認狀況下,Commons Modeler庫使用 org.apache.commons.modeler.BaseModelMBean類。

有如下兩種狀況。其中可能須要對BaseModelMBean類進行擴展:

  • 須要覆蓋託管資源的屬性或方法
  • 須要添加在託管資源中沒有定義的屬性或方法

在org.apahce.catalina.mbeans包下,Catalina 提供了BaseModelMBean類的不少子類,能夠用來實現上面的需求。

Registry類.

org.apahce.commons.modeler.Registry類定義了不少方法,下面是可使用該類作的事情。

  • 獲取 javax.managedment.MBeanServer類的一個實例,因此不須要在調用javax.managedment.MbeanServerFactory類的createMBeanServer方法了
  • 使用 loadRegistry方法獲取MBean的描述文件
  • 建立一個ManagedBean對象,用於建立模型MBean的實例。

ManagedMBean

  ManagedMBean對象描述了一個模型MBean,該類用於取代javax.managedment.MBeanInfo對象。

BaseModelMBean

  org.apache.commons.modeler.BaseModelMbean類實現了 javax.managedment.modelmbean.ModelMBean接口,使用這個類,就不須要使用javax.managedment.modelmbean.RequiredMoldeMBean這個類了,

  該類用一個比較有用的字段是resource字段。resource字段表示該模型MBean管理的資源。resource字段的定義以下;

protected  java.lang.Object resource = null;

 

使用Modeler庫 API

下面代碼給出了想要管理器對象Car類的定義

 1 package myex20.pyrmont.modelmbeantest2;
 2 
 3 /**
 4  * <p>
 5  * <b>Title:Car.java</b>
 6  * </p>
 7  * <p>
 8  * Copyright:ChenDong 2018
 9  * </p>
10  * <p>
11  * Company:僅學習時使用
12  * </p>
13  * <p>
14  * 類功能描述:modelmbeantest2 中 要被管理的對象
15  * </p>
16  * 
17  * @author 陳東
18  * @date 2018年12月10日 下午10:20:53
19  * @version 1.0
20  */
21 public class Car {
22     public Car() {
23         System.out.println("Car constructor");
24     }
25 
26     private String color = "red";
27 
28     public String getColor() {
29 
30         return this.color;
31     }
32 
33     public void setColor(String color) {
34         this.color = color;
35     }
36 
37     public void drive() {
38         System.out.println("Baby  you can drive my " + color + " Car");
39     }
40 
41 }

  使用Commons Modeler 庫,不須要使用硬編碼的方式,將託管對象的全部屬性和方法都寫在代碼中,相反,能夠將他們寫在一個xml文件中,做爲MBean的描述符文件,在這個例子當中,這樣的文檔是car-mbean-descriptor.xml文件,以下面所所示

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mbeans-descriptors PUBLIC
 "-//Apache Software Foundation//DTD Model MBeans Configuration File"
 "http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd">
 
<mbeans-descriptors>

  <mbean name="myMBean"
    className="javax.management.modelmbean.RequiredModelMBean"
    description="The ModelMBean that manages our Car object"
    type="ex20.pyrmont.modelmbeantest.Car">

    <attribute name="Color"
      description="The car color"
      type="java.lang.String"/>

    <operation name="drive"
      description="drive method"
      impact="ACTION"
      returnType="void">
      <parameter name="driver" description="the driver parameter"
        type="java.lang.String"/>
    </operation>

  </mbean>

</mbeans-descriptors>

 

那麼咱們寫完這個描述文件以後,就須要一個在寫一個代理類ModelAgent.java,具體看下面哈

 

package myex20.pyrmont.modelmbeantest2;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.management.Attribute;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.modelmbean.ModelMBean;

import org.apache.commons.modeler.ManagedBean;
import org.apache.commons.modeler.Registry;

/**
 * <p>
 * <b>Title:ModelAgent.java</b>
 * </p>
 * <p>
 * Copyright:ChenDong 2018
 * </p>
 * <p>
 * Company:僅學習時使用
 * </p>
 * <p>
 * 類功能描述: modelmbeantest2包下的代理類
 * </p>
 * 
 * @author 陳東
 * @date 2018年12月11日 下午7:43:28
 * @version 1.0
 */
public class ModelAgent {
    /**
     * <p>
     * 做用1:獲取 {@link javax.management.MBeanServer }
     * </p>
     * 
     * <p>
     * 做用2:使用loadRegistry方法來讀取mbean描述文件;
     * </p>
     * 
     * <p>
     * 做用3:建立一個@
     * {@link org.apache.commons.modeler.ManagedBean}用於建立一個{@code ModelMBean}
     * </p>
     */
    private Registry registry;

    private MBeanServer mbeanServer;

    public ModelAgent() {
        registry = createRegistry();
        mbeanServer = Registry.getServer();
    }

    public MBeanServer getMBeanServer() {
        return mbeanServer;
    }

    /**
     * 
     * 
     * <p>
     * Title: createRegistrt
     * </p>
     * 
     * @date 2018年12月11日 下午8:28:44
     * 
     *       <p>
     *       功能描述:建立Registry,
     *       </p>
     * 
     * @return
     */
    private Registry createRegistry() {

        Registry registry = null;

        try {
            URL url = ModelAgent.class.getResource("/myex20/pyrmont/modelmbeantest2/car-mbean-descriptor.xml");
            InputStream io = url.openStream();
            Registry.loadRegistry(io);
            registry = Registry.getRegistry();
        } catch (Exception e) {

            e.printStackTrace();
        }
        return registry;
    }

    /**
     * 
     * 
     * <p>
     * Title: createModleMBean
     * </p>
     * <p>
     * 功能描述:用於建立指定名字的 ModelMBean 這裏的名字必須是 mbean描述文件中的 mbean 元素的name屬性所指定的才能夠
     * 不然返回null
     * </p>
     * 
     * @date 2018年12月11日 下午8:46:54
     * 
     * 
     * 
     * @param mbeanName
     * @return
     * @throws Exception
     */
    private ModelMBean createModleMBean(String mbeanName) throws Exception {
        // 根據指定的名字去找mbean描述文件中對應的配置所表明的 ManagedBean對象
        ManagedBean managed = registry.findManagedBean(mbeanName);
        if (managed == null) {
            System.out.println("ManagedBean is null");
            return null;
        }
        // 建立ModelMBean
        ModelMBean mbean = managed.createMBean();

        return mbean;
    }

    /**
     * 
     * 
     * <p>
     * Title: createObjectName
     * </p>
     * 
     * @date 2018年12月11日 下午8:45:25
     * 
     *       <p>
     *       功能描述:建立用於向mbean服務器註冊時爲MBean作惟一標識 的ObjectName
     *       </p>
     * 
     * @return
     */
    private ObjectName createObjectName() {
        ObjectName objectname = null;
        String domain = mbeanServer.getDefaultDomain();
        try {
            objectname = new ObjectName(domain + ":type=MyCar");
        } catch (MalformedObjectNameException e) {

            e.printStackTrace();
        }

        return objectname;
    }

    public static void main(String[] args) {
        // 實例化代理類
        ModelAgent agent = new ModelAgent();
        // 使用代理類 獲取MBeanServer
        MBeanServer server = agent.getMBeanServer();
        // 要被託管的資源
        Car car = new Car();
        // 建立ObjectName
        ObjectName objectName = agent.createObjectName();

        try {
            // 建立ModelMBean對象 名字必須在mbean 描述文件中有對應mbean元素
            ModelMBean modelMBean = agent.createModleMBean("myMBean");
            // 將託管資源 與 modelMBean對象關聯起來
            /**
             * 在建立了ModelMBean對象以後,須要調用ModelMbean接口的setManagedResource方法將
             * ModelMBean與其託管的資源相互關聯, public void
             * setManagedResource(java.lang.Object managedResource,
             * java.lang.String managedResourceType) throws MBeanException,
             * RuntimeOperationsException, InstanceNotFoundException,
             * InvalidTargetObjectTypeException ; managedResourceType 目前只支持
             * ObjectReference
             */
            modelMBean.setManagedResource(car, "ObjectReference");
            // 將modelMBean 註冊到 mbeanServer
            server.registerMBean(modelMBean, objectName);

        } catch (Exception e) {

            e.printStackTrace();
        }

        // 管理這個託管資源
        try {

            Attribute attribute = new Attribute("Color", "green");
            server.setAttribute(objectName, attribute);
            String color = (String) server.getAttribute(objectName, "Color");
            System.out.println("mbeanserver getAttribute  Color:" + color);
            System.out.println("Car's Color:" + car.getColor());

            attribute = new Attribute("Color", "blue");
            server.setAttribute(objectName, attribute);
            color = (String) server.getAttribute(objectName, "Color");
            System.out.println("mbeanserver getAttribute  Color:" + color);
            System.out.println("Car's Color:" + car.getColor());

            server.invoke(objectName, "drive", null, null);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

運行main方法後的結果

十二月 11, 2018 9:41:28 下午 org.apache.commons.modeler.Registry loadRegistry
信息: Loading registry information
十二月 11, 2018 9:41:28 下午 org.apache.commons.modeler.Registry getRegistry
信息: Creating new Registry instance
十二月 11, 2018 9:41:28 下午 org.apache.commons.modeler.Registry getServer
信息: Creating MBeanServer
十二月 11, 2018 9:41:28 下午 org.apache.commons.modeler.Registry loadRegistry
信息: Loading registry information
Car constructor
mbeanserver getAttribute  Color:green
Car's Color:green
mbeanserver getAttribute  Color:blue
Car's Color:blue
Baby  you can drive my blue Car

看下咱們在使用了Commons Modeler庫以後 減小了好多代碼吧

Catalina中的MBean

  Catalina 在 org.apache.catalina.mbeans包中提供了一系列的MBean類,這些MBean類都直接 或者間接的繼承自 org.apahce.commons.modeler.BaseModelMBean類,下面會爲你們展現一下 Tomcat 4 中  三個最重要的MBean類,分別是ClassNameMBean類,

StandardServerMBean類、和MBeanFactory類,還有一個重要的工具類 MBeanUtil類。

BaseModelMBean類

  由於下面要講解的類直接或者間接都會繼承該類,因此有必要講解下 該類的一些 重要的屬性 以及方法

首先 有一個 java.lang.Object 類型名爲 resource的變量 表示 託管資源的實例對象

protected Object resource = null;

還有一個重要的方法也就 將託管資源 和 該ModelMBean相關聯的方法 setManagedResource(Object resource,String type),看下面的展現

    /**
     * 
     * 
     * <p>
     * Title: setManagedResource
     * </p>
     * 
     * @date 2018年12月11日 下午10:13:06
     * 
     *       <p>
     *       功能描述: 將 指定的 託管資源 resource ,綁定到當前的ModelMBean中
     *       </p>
     * 
     * @param resource 指定的託管資源
     * @param type 指定type 目前只支持 {@code objectreference} 
     * @throws InstanceNotFoundException
     * @throws InvalidTargetObjectTypeException 若 type 不爲 {@code objectreference} 拋出錯誤
     * @throws MBeanException
     * @throws RuntimeOperationsException 若 指定的託管資源resource是null 則拋出錯誤
     */
    public void setManagedResource(Object resource, String type) throws InstanceNotFoundException,
            InvalidTargetObjectTypeException, MBeanException, RuntimeOperationsException {
        if (resource == null) {
            throw new RuntimeOperationsException(new IllegalArgumentException("Managed resource is null"),
                    "Managed resource is null");
        } else if (!"objectreference".equalsIgnoreCase(type)) {
            throw new InvalidTargetObjectTypeException(type);
        } else {
            this.resource = resource;
        }
    }

 

ClassNameMBean

  org.apahce.catalina.mbeans.ClassNameMBean類 繼承自 org.apache.commons.modeler.BaseModelMBean類,它提供了一個屬性className,用於表示託管資源的類名,詳細的內容看下面

 

 1 package org.apache.catalina.mbeans;
 2 
 3 import javax.management.MBeanException;
 4 import javax.management.RuntimeOperationsException;
 5 import org.apache.commons.modeler.BaseModelMBean;
 6 
 7 /**
 8  * 
 9  * <p>
10  * <b>Title:ClassNameMBean.java</b>
11  * </p>
12  * <p>
13  * Copyright:ChenDong 2018
14  * </p>
15  * <p>
16  * Company:僅學習時使用
17  * </p>
18  * <p>
19  * 類功能描述:這個類建立一個名爲className屬性,該屬性將託管對象的徹底限定類名報告爲其值。
20  * </p>
21  * 
22  * @author 陳東
23  * @date 2018年12月11日 下午10:18:52
24  * @version 1.0
25  */
26 public class ClassNameMBean extends BaseModelMBean {
27 
28     // ---------------------------------------------------------- Constructors
29 
30     /**
31      * 
32      * 用默認的<code>ModelMBeanInfo</code>信息構造ModelMBean。
33      * 
34      * @exception MBeanException
35      *                若是對象的初始化引起異常
36      * @exception RuntimeOperationsException
37      *                若是發生錯誤
38      */
39     public ClassNameMBean() throws MBeanException, RuntimeOperationsException {
40 
41         super();
42 
43     }
44 
45     // ------------------------------------------------------------ Properties
46 
47     /**
48      * 返回其託管資源類的徹底限定名
49      */
50     public String getClassName() {
51 
52         return (this.resource.getClass().getName());
53 
54     }
55 
56 }

  ClassNameMBean類時BaseModelMBean類的子類,其屬性className在託管資源中是不可見的,mbeans-descriptors.xml文件中的不少mbean元素使用該類做爲其ModelMBean的類型。

StandardServerMBean類

  StandardServerMBean類繼承自 org.apache.commons.modeler.BaseModelMBean類,用於管理 org.apache.catalina.core.StandardServer類的實例,StandardServerMBean類是ModelMBean類的一個示例,它重寫了託管資源的store方法,當管理應用程序調用store方法的時候,實際上會執行StandardServerMBean實例的store方法,而不是託管資源StandardServer對象的store方法,

 1 package org.apache.catalina.mbeans;
 2 
 3 
 4 import javax.management.InstanceNotFoundException;
 5 import javax.management.MBeanException;
 6 import javax.management.MBeanServer;
 7 import javax.management.RuntimeOperationsException;
 8 import org.apache.catalina.Server;
 9 import org.apache.catalina.ServerFactory;
10 import org.apache.catalina.core.StandardServer;
11 import org.apache.commons.modeler.BaseModelMBean;
12 
13 
14 /**
15  * 
16  * <p>
17  * <b>Title:StandardServerMBean.java</b>
18  * </p>
19  * <p>
20  * Copyright:ChenDong 2018
21  * </p>
22  * <p>
23  * Company:僅學習時使用
24  * </p>
25  * <p>
26  * 類功能描述: {@code org.apache.catalina.core.StandardServer} 組件的ModelMBean實現。
27  * </p>
28  * 
29  * @author 陳東
30  * @date 2018年12月13日 下午7:36:09
31  * @version 1.0
32  */
33 
34 public class StandardServerMBean extends BaseModelMBean {
35 
36 
37     // ------------------------------------------------------- Static Variables
38 
39 
40     /**
41      * 應用程序的<code>MBeanServer</code> 組件
42      */
43     private static MBeanServer mserver = MBeanUtils.createServer();
44 
45 
46     // ----------------------------------------------------------- Constructors
47 
48 
49     /**
50      *
51      * 使用默認的<code>ModelMBeanInfo</code> 實現一個<code>ModelMBean</code>
52      * 
53      * @exception MBeanException
54      *                若是對象的初始化器引起異常
55      * @exception RuntimeOperationsException
56      *                
57      */
58     public StandardServerMBean() throws MBeanException, RuntimeOperationsException {
59 
60         super();
61 
62     }
63 
64 
65     // ------------------------------------------------------------- Attributes
66 
67 
68     // ------------------------------------------------------------- Operations
69 
70 
71     /**
72      * 
73      * 將整個<code>Server</code>的配置信息寫入{@code server.xml}配置文件。
74      * 
75      * @exception InstanceNotFoundException
76      *                若是找不到託管資源對象
77      * @exception MBeanException
78      *                若是對象的初始化器拋出異常,或者不支持持久性
79      * @exception RuntimeOperationsException
80      *                若是持久性機制報告了異常
81      */
82     public synchronized void store() throws InstanceNotFoundException,
83         MBeanException, RuntimeOperationsException {
84 
85         Server server = ServerFactory.getServer();
86         if (server instanceof StandardServer) {
87             try {
88                 ((StandardServer) server).store();
89             } catch (Exception e) {
90                 throw new MBeanException(e, "Error updating conf/server.xml");
91             }
92         }
93 
94     }
95 
96 
97 }
StandardServerMBean 是一種模型MBean,繼承自BaseModelMBean,並重寫了託管資源(org.apache.catalina.core.StandardServer)的一個方法
相關文章
相關標籤/搜索