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實例的屬性。瀏覽器
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來管理一個java對象,須要執行如下步驟。
標準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難度更大一些,可是也不須要爲可管理的對象修改原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對象相關聯;
在建立了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接口,該接口的實例會將託管資源的屬性 和方法提供給代理層。
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)
下面是參數列表:
可使用下面的構造函數建立一個 ModelMBeanOperationInfo對象
public ModelMBeanOperationInfo(String name, String description, MBeanParameterInfo[] signature, String type, int impact, Descriptor descriptor)
下面是參數列表;
/** * 方法返回信息但不改變任何狀態 */ public static final int INFO = 0;
/** * 指示該操做是寫式的:它具備效果,但不從MBean返回任何信息 */ public static final int ACTION = 1;
/** *指示該操做既讀又寫:它具備效果,而且還返回來自MBean的信息 */ public static final int ACTION_INFO = 2;
/** * 指示操做的影響是未知的,或者沒法使用其餘值之一來表示。 */ public static final int UNKNOWN = 3;
只能夠選擇上面的四種
咱們仍是使用原來的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;
從上面的例子咱們已經看出來了 最麻煩的就是建立ModelMBeanInfo信息了,若是這個步驟不能夠簡化 那麼這個ModelMBean將不具有可用性,
那麼爲了簡化建立ModelMBeanInfo信息引入了一個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描述符是一個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,包含建立對應ModelMBeanInfo對象的信息。mbean元素的定義以下所示:
<!ELEMENT mbean(descriptor?,attribute*,constructor*,notification*,operation*)>
mbean元素定義了具體的規範,mbean元素能夠有一個可選的descriptor元素,0個或者多個attribute元素。0個或者多個constructor元素,0個或者多個notification元素。0個或者多個operation元素。
mbean元素能夠有以下的屬性:
使用attribute元素描述MBean的javaBean屬性。attribute元素有一個可選的descripotr元素,attribute元素能夠由以下的屬性:
operation元素描述了模型MBean 中要暴露給管理應用程序的公共方法,它能夠有.個或者多個parameter子元素和以下的屬性:
parameter元素描述了將要傳遞給構造函數 或者 方法的參數,它能夠有以下的屬性:
在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元素描述。
使用Commons Modeler庫,須要在mbean元素的className屬性中指明自定義的模型MBean的類型,默認狀況下,Commons Modeler庫使用 org.apache.commons.modeler.BaseModelMBean類。
有如下兩種狀況。其中可能須要對BaseModelMBean類進行擴展:
在org.apahce.catalina.mbeans包下,Catalina 提供了BaseModelMBean類的不少子類,能夠用來實現上面的需求。
org.apahce.commons.modeler.Registry類定義了不少方法,下面是可使用該類作的事情。
ManagedMBean對象描述了一個模型MBean,該類用於取代javax.managedment.MBeanInfo對象。
org.apache.commons.modeler.BaseModelMbean類實現了 javax.managedment.modelmbean.ModelMBean接口,使用這個類,就不須要使用javax.managedment.modelmbean.RequiredMoldeMBean這個類了,
該類用一個比較有用的字段是resource字段。resource字段表示該模型MBean管理的資源。resource字段的定義以下;
protected java.lang.Object resource = null;
下面代碼給出了想要管理器對象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 在 org.apache.catalina.mbeans包中提供了一系列的MBean類,這些MBean類都直接 或者間接的繼承自 org.apahce.commons.modeler.BaseModelMBean類,下面會爲你們展現一下 Tomcat 4 中 三個最重要的MBean類,分別是ClassNameMBean類,
StandardServerMBean類、和MBeanFactory類,還有一個重要的工具類 MBeanUtil類。
由於下面要講解的類直接或者間接都會繼承該類,因此有必要講解下 該類的一些 重要的屬性 以及方法
首先 有一個 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; } }
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類繼承自 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)的一個方法