一、前言
動態MBean是在運行期才定義它的屬性和方法,也就是說它有什么屬性和方法是可以動態改變的。動態MBean主要利用一些輔助類(構造函數類MBeanConstructorInfo、屬性類MBeanAttributeInfo、方法類MBeanOperationInfo)來完成這個功能,所有的動態MBean必須實現DynamicMBean接口。DynamicMBean寫好后,使用方法和第一篇文章中普通的MBean一樣。
給出一個動態MBean的實例,這個實例最初動態構了一個Name屬性及一個print方法,當我們執行它的print方法之后,又給此MBean新增了一個print1方法。實例的代碼如下:
二、實例
1、HelloDynamic類
import java.lang.reflect.Constructor;
import java.util.Iterator;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.DynamicMBean;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.ReflectionException;
/**
?* @author Sunny Peng
?* @author change by Chen.Gang, add a feature for dynamic add operation
?* @version 1.0
?*/
public class HelloDynamic implements DynamicMBean {
??? //這是我們的屬性名稱
??? private String name;
??? private MBeanInfo mBeanInfo = null;
??? private String className;
??? private String description;
??? private MBeanAttributeInfo[] attributes;
??? private MBeanConstructorInfo[] constructors;
??? private MBeanOperationInfo[] operations;
??? MBeanNotificationInfo[] mBeanNotificationInfoArray;
??? public HelloDynamic() {
??????? init();
??????? buildDynamicMBean();
??? }
??? private void init() {
??????? className = this.getClass().getName();
??????? description = "Simple implementation of a dynamic MBean.";
??????? attributes = new MBeanAttributeInfo[1];
??????? constructors = new MBeanConstructorInfo[1];
??????? operations = new MBeanOperationInfo[1];
??????? mBeanNotificationInfoArray = new MBeanNotificationInfo[0];
??? }
??? private void buildDynamicMBean() {
??????? //設定構造函數
??????? Constructor[] thisconstructors = this.getClass().getConstructors();
??????? constructors[0] = new MBeanConstructorInfo("HelloDynamic(): Constructs a HelloDynamic object", thisconstructors[0]);
??????? //設定一個屬性
??????? attributes[0] = new MBeanAttributeInfo("Name", "java.lang.String", "Name: name string.", true, true, false);
??????? //operate method 我們的操作方法是print
??????? MBeanParameterInfo[] params = null;//無參數
??????? operations[0] = new MBeanOperationInfo("print", "print(): print the name", params, "void", MBeanOperationInfo.INFO);
??????? mBeanInfo = new MBeanInfo(className, description, attributes, constructors, operations, mBeanNotificationInfoArray);
??? }
??? //動態增加一個print1方法
??? private void dynamicAddOperation() {
??????? init();
??????? operations = new MBeanOperationInfo[2];//設定數組為兩個
??????? buildDynamicMBean();
??????? operations[1] = new MBeanOperationInfo("print1", "print1(): print the name", null, "void", MBeanOperationInfo.INFO);
??????? mBeanInfo = new MBeanInfo(className, description, attributes, constructors, operations, mBeanNotificationInfoArray);
??? }
??? public Object getAttribute(String attribute_name) {
??????? if (attribute_name != null)
??????????? return null;
??????? if (attribute_name.equals("Name"))
??????????? return name;
??????? return null;
??? }
??? public void setAttribute(Attribute attribute) {
??????? if (attribute == null)
??????????? return;
??????? String Name = attribute.getName();
??????? Object value = attribute.getValue();
??????? try {
??????????? if (Name.equals("Name")) {
??????????????? // if null value, try and see if the setter returns any exception
??????????????? if (value == null) {
??????????????????? name = null;
??????????????????? // if non null value, make sure it is assignable to the attribute
??????????????? } else if ((Class.forName("java.lang.String")).isAssignableFrom(value.getClass())) {
??????????????????? name = (String) value;
??????????????? }
??????????? }
??????? } catch (Exception e) {
??????????? e.printStackTrace();
??????? }
??? }
??? public AttributeList getAttributes(String[] attributeNames) {
??????? if (attributeNames == null)
??????????? return null;
??????? AttributeList resultList = new AttributeList();
??????? // if attributeNames is empty, return an empty result list
??????? if (attributeNames.length == 0)
??????????? return resultList;
??????? for (int i = 0; i < attributeNames.length; i++) {
??????????? try {
??????????????? Object value = getAttribute(attributeNames[i]);
??????????????? resultList.add(new Attribute(attributeNames[i], value));
??????????? } catch (Exception e) {
??????????????? e.printStackTrace();
??????????? }
??????? }
??????? return resultList;
??? }
??? public AttributeList setAttributes(AttributeList attributes) {
??????? if (attributes == null)
??????????? return null;
??????? AttributeList resultList = new AttributeList();
??????? // if attributeNames is empty, nothing more to do
??????? if (attributes.isEmpty())
??????????? return resultList;
??????? // for each attribute, try to set it and add to the result list if successfull
??????? for (Iterator i = attributes.iterator(); i.hasNext();) {
??????????? Attribute attr = (Attribute) i.next();
??????????? try {
??????????????? setAttribute(attr);
??????????????? String name = attr.getName();
??????????????? Object value = getAttribute(name);
??????????????? resultList.add(new Attribute(name, value));
??????????? } catch (Exception e) {
??????????????? e.printStackTrace();
??????????? }
??????? }
??????? return resultList;
??? }
??? public Object invoke(String operationName, Object params[], String signature[]) throws MBeanException, ReflectionException {
??????? // Check for a recognized operation name and call the corresponding operation
??????? if (operationName.equals("print")) {
??????????? //具體實現我們的操作方法print
??????????? System.out.println("Hello, " + name + ", this is HellDynamic!");
??????????? dynamicAddOperation();
??????????? return null;
??????? } else if (operationName.equals("print1")) {
??????????? System.out.println("這是動態增加的一方法print1");
??????????? return null;
??????? } else {
??????????? // unrecognized operation name:
??????????? throw new ReflectionException(new NoSuchMethodException(operationName), "Cannot find the operation " + operationName + " in " + className);
??????? }
??? }
??? public MBeanInfo getMBeanInfo() {
??????? return mBeanInfo;
??? }
}
?
說明:
??? * 實現于接口DynamicMBean
??? * 借助于各種輔助類完成一個類的構造。構造函數類MBeanConstructorInfo、屬性類MBeanAttributeInfo、方法類MBeanOperationInfo
??? * 這里所有public方法是實現于DynamicMBean的。主要提供:setAttribute設置屬性、 getAttribute取得屬性、setAttributes設置一組屬性、getAttributes取得一組屬性、invoke方法調用、 getMBeanInfo MBeanServer由這個方法得到關鍵的MBean類的構造信息。
2、HelloAgent類
前面說了HelloDynamic和普通MBean的使用方法是一樣的,因此HelloAgent和第一篇的HelloAgent基本一樣,就是把Hello改成HelloDynamic而已。為了實例完整,也一并帖出來吧。
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
import com.sun.jdmk.comm.HtmlAdaptorServer;
public class HelloAgent {
??? public static void main(String[] args) throws Exception {
??????? MBeanServer server = MBeanServerFactory.createMBeanServer();
??????? ObjectName helloName = new ObjectName("chengang:name=HelloDynamic");
??????? HelloDynamic hello = new HelloDynamic();
??????? server.registerMBean(hello, helloName);
??????? ObjectName adapterName = new ObjectName("HelloAgent:name=htmladapter,port=8082");
??????? HtmlAdaptorServer adapter = new HtmlAdaptorServer();
??????? server.registerMBean(adapter, adapterName);
??????? adapter.start();
??????? System.out.println("start.....");
??? }
}
3、運行
先運行HelloAgent。再打開瀏覽器,輸入網址:http://localhost:8082/。單擊進入“name=HelloDynamic ”項,執行print方法后再回到上一頁面你會發現又多了一個print1方法。
4、總結
動態MBean的代碼稍顯復雜,但對于一些特殊需求的情況,它將顯示出強大威力。而且它還是模型MBeans(Model MBeans)的基礎。不過在一般的項目中,動態MBean還是用得比較少,所謂利器深藏之而不用,非常時方現光芒。