阅读更多
一、前言
动态MBean是在运行期才定义它的属性和方法,也就是说它有什么属性和方法是可以动态改变的。动态MBean主要利用一 些辅助类(构造函数类MBeanConstructorInfo、属性类MBeanAttributeInfo、方法类 MBeanOperationInfo)来完成这个功能,所有的动态MBean必须实现DynamicMBean接口。DynamicMBean写好后, 使用方法和第一篇文章中普通的MBean一样。
给出一个动态MBean的实例,这个实例最初动态构了一个Name属性及一个print方法,当我们执行它的print方法之后,又给此MBean新增了一个print1方法。实例的代码如下:
二、实例
1、HelloDynamic类
1.import java.lang.reflect.Constructor;
2.import java.util.Iterator;
3.import javax.management.Attribute;
4.import javax.management.AttributeList;
5.import javax.management.DynamicMBean;
6.import javax.management.MBeanAttributeInfo;
7.import javax.management.MBeanConstructorInfo;
8.import javax.management.MBeanException;
9.import javax.management.MBeanInfo;
10.import javax.management.MBeanNotificationInfo;
11.import javax.management.MBeanOperationInfo;
12.import javax.management.MBeanParameterInfo;
13.import javax.management.ReflectionException;
14.
15./**
16. * @author Sunny Peng
17. * @author change by Chen.Gang, add a feature for dynamic add operation
18. * @version 1.0
19. */
20.public class HelloDynamic implements DynamicMBean {
21. //这是我们的属性名称
22. private String name;
23. private MBeanInfo mBeanInfo = null;
24. private String className;
25. private String description;
26. private MBeanAttributeInfo[] attributes;
27. private MBeanConstructorInfo[] constructors;
28. private MBeanOperationInfo[] operations;
29. MBeanNotificationInfo[] mBeanNotificationInfoArray;
30.
31. public HelloDynamic() {
32. init();
33. buildDynamicMBean();
34. }
35.
36. private void init() {
37. className = this.getClass().getName();
38. description = "Simple implementation of a dynamic MBean.";
39. attributes = new MBeanAttributeInfo[1];
40. constructors = new MBeanConstructorInfo[1];
41. operations = new MBeanOperationInfo[1];
42. mBeanNotificationInfoArray = new MBeanNotificationInfo[0];
43. }
44.
45. private void buildDynamicMBean() {
46. //设定构造函数
47. Constructor[] thisconstructors = this.getClass().getConstructors();
48. constructors[0] = new MBeanConstructorInfo("HelloDynamic(): Constructs a HelloDynamic object", thisconstructors[0]);
49. //设定一个属性
50. attributes[0] = new MBeanAttributeInfo("Name", "java.lang.String", "Name: name string.", true, true, false);
51. //operate method 我们的操作方法是print
52. MBeanParameterInfo[] params = null;//无参数
53. operations[0] = new MBeanOperationInfo("print", "print(): print the name", params, "void", MBeanOperationInfo.INFO);
54. mBeanInfo = new MBeanInfo(className, description, attributes, constructors, operations, mBeanNotificationInfoArray);
55. }
56.
57. //动态增加一个print1方法
58. private void dynamicAddOperation() {
59. init();
60. operations = new MBeanOperationInfo[2];//设定数组为两个
61. buildDynamicMBean();
62. operations[1] = new MBeanOperationInfo("print1", "print1(): print the name", null, "void", MBeanOperationInfo.INFO);
63. mBeanInfo = new MBeanInfo(className, description, attributes, constructors, operations, mBeanNotificationInfoArray);
64. }
65.
66. public Object getAttribute(String attribute_name) {
67. if (attribute_name != null)
68. return null;
69. if (attribute_name.equals("Name"))
70. return name;
71. return null;
72. }
73.
74. public void setAttribute(Attribute attribute) {
75. if (attribute == null)
76. return;
77. String Name = attribute.getName();
78. Object value = attribute.getValue();
79. try {
80. if (Name.equals("Name")) {
81. // if null value, try and see if the setter returns any exception
82. if (value == null) {
83. name = null;
84. // if non null value, make sure it is assignable to the attribute
85. } else if ((Class.forName("java.lang.String")).isAssignableFrom(value.getClass())) {
86. name = (String) value;
87. }
88. }
89. } catch (Exception e) {
90. e.printStackTrace();
91. }
92. }
93.
94. public AttributeList getAttributes(String[] attributeNames) {
95. if (attributeNames == null)
96. return null;
97. AttributeList resultList = new AttributeList();
98. // if attributeNames is empty, return an empty result list
99. if (attributeNames.length == 0)
100. return resultList;
101. for (int i = 0; i < attributeNames.length; i++) {
102. try {
103. Object value = getAttribute(attributeNames[i]);
104. resultList.add(new Attribute(attributeNames[i], value));
105. } catch (Exception e) {
106. e.printStackTrace();
107. }
108. }
109. return resultList;
110. }
111.
112. public AttributeList setAttributes(AttributeList attributes) {
113. if (attributes == null)
114. return null;
115. AttributeList resultList = new AttributeList();
116. // if attributeNames is empty, nothing more to do
117. if (attributes.isEmpty())
118. return resultList;
119. // for each attribute, try to set it and add to the result list if successfull
120. for (Iterator i = attributes.iterator(); i.hasNext();) {
121. Attribute attr = (Attribute) i.next();
122. try {
123. setAttribute(attr);
124. String name = attr.getName();
125. Object value = getAttribute(name);
126. resultList.add(new Attribute(name, value));
127. } catch (Exception e) {
128. e.printStackTrace();
129. }
130. }
131. return resultList;
132. }
133.
134. public Object invoke(String operationName, Object params[], String signature[]) throws MBeanException, ReflectionException {
135. // Check for a recognized operation name and call the corresponding operation
136. if (operationName.equals("print")) {
137. //具体实现我们的操作方法print
138. System.out.println("Hello, " + name + ", this is HellDynamic!");
139. dynamicAddOperation();
140. return null;
141. } else if (operationName.equals("print1")) {
142. System.out.println("这是动态增加的一方法print1");
143. return null;
144. } else {
145. // unrecognized operation name:
146. throw new ReflectionException(new NoSuchMethodException(operationName), "Cannot find the operation " + operationName + " in " + className);
147. }
148.
149. }
150.
151. public MBeanInfo getMBeanInfo() {
152. return mBeanInfo;
153. }
154.}
说明:
* 实现于接口DynamicMBean
* 借助于各种辅助类完成一个类的构造。构造函数类MBeanConstructorInfo、属性类MBeanAttributeInfo、方法类MBeanOperationInfo
* 这里所有public方法是实现于DynamicMBean的。主要提供:setAttribute设置属性、 getAttribute取得属性、setAttributes设置一组属性、getAttributes取得一组属性、invoke方法调用、 getMBeanInfo MBeanServer由这个方法得到关键的MBean类的构造信息。
2、HelloAgent类
前面说了HelloDynamic和普通MBean的使用方法是一样的,因此HelloAgent和第一篇的HelloAgent基本一样,就是把Hello改成HelloDynamic而已。为了实例完整,也一并帖出来吧。
1.import javax.management.MBeanServerFactory;
2.import javax.management.ObjectName;
3.import com.sun.jdmk.comm.HtmlAdaptorServer;
4.public class HelloAgent {
5. public static void main(String[] args) throws Exception {
6. MBeanServer server = MBeanServerFactory.createMBeanServer();
7. ObjectName helloName = new ObjectName("chengang:name=HelloDynamic");
8. HelloDynamic hello = new HelloDynamic();
9. server.registerMBean(hello, helloName);
10. ObjectName adapterName = new ObjectName("HelloAgent:name=htmladapter,port=8082");
11. HtmlAdaptorServer adapter = new HtmlAdaptorServer();
12. server.registerMBean(adapter, adapterName);
13. adapter.start();
14. System.out.println("start.....");
15. }
16.}
3、运行
先运行HelloAgent。再打开浏览器,输入网址:http://localhost:8082/。单击进入“name=HelloDynamic ”项,执行print方法后再回到上一页面你会发现又多了一个print1方法。
4、总结
动态MBean的代码稍显复杂,但对于一些特殊需求的情况,它将显示出强大威力。而且它还是模型MBeans(Model MBeans)的基础。不过在一般的项目中,动态MBean还是用得比较少,所谓利器深藏之而不用,非常时方现光芒。