JMX架构的了解 (MBean部分)
板桥里人 http://www.jdon.com 2003/1/5
我们前章举例的HelloMBean是StandardMBean,这是JMX中的MBean的一种,还有一种 叫DynamicMBean,这是JMX在运行期间能够控制它,
无论哪种MBean,他们的区别只是在他们如何被开发,而不是在它们如何被管理, JMX的Agent提供了处理这两种类型的抽象的处理方法,也就是说,一旦这两种MBean
被JMX的Agent管理,这两种MBean在外界看来没什么区别。
一个标准的standard MBean的Java class是通过它的attributes和operations
被外界管理的,Attributes是内部的一些属性变量,它通过getter 和 setter方法被外界管理 在HelloMBean中,它们是
public String getName();
public void setName(String name);
Operations 是这个class中其它愿意被管理的方法,在HellMBean中是
public void print()
所有这些方法需要在MBean接口中定义,然后通过introspection(内省机制) 显露给一个agent, 上述方法是制造一个可管理资源的最直接办法。
DynamicMBean
而在开发一个DynamicMBean时,attributes 和operations是通过方法调用 间接的显露给agent的。DynamicMBean
适合管理那些已经存在的资源和代码。
需要被JMX的Agent认为是 DynamicMBean,这个Java class或它的子类必须继承 一个DynamicMBean的标准接口。
getMBeanInfo:
DynamicMBean不象StandardMBean那样通过introspection(内省机制)向外界 显露他的attributes和operations,而是通过在运行时,返回这个方法的值来向
外界显露他的attribute names 和 types 以及 operation signatures 。 这个方法返回的是MBeanInfo实例.
getAttribute 和 getAttributes
这是获得相应的attribute name属性名称或属性名称表的值,这个类似StandardMBean的 getter方法,不同点是由调用者提供所需要的属性名,如
public Object getAttribute(String attribute_name) 不同于StandardMBean的getXXXX(Attribute_name)。
setAttribute 和 setAttributes
这个类似StandardMBean的setter方法, 设置相应属性的name-value对。
invoke
invoke方法是让外界来调用DynamicMBean的操作,这儿调用者必须提供 操作名称 作为参数传递的object和这些参数的类型,具体如:
public Object invoke(String operationName, Object params[],
String signature[])
当DynamicMBean在JMX agent中注册后,DynamicMBean其实就和StandardMBean
是一样的,外界将首先通过getMBeanInfo获得一个管理接口,其中包含attributes 和 operations
名称,然后才将调用DynamicMBean的getters, setters 和invoke方法,
MBean原始类
从上面可以看到,MBean有一些自己规定的诸如MBeanInfo这样的原始类,一共有如下几种:
MBeanInfo - 罗列出所有的属性attribute, 操作operations, 构造器constructor
和 notification
MBeanFeatureInfo - 下面类的子类
MBeanAttributeInfo - 描述一个属性attribute
MBeanConstructorInfo - 描述一个构造器constructor MBean构造器是由签名单独地定义,这个签名是参数的次序和类型.
MBeanOperationInfo - 描述一个操作operation
MBeanParameterInfo - 描述一个操作或构造器的参数
MBeanNotificationInfo - 描述一个notification
通过与使用这些原始类,将你的具体资源就可以动态的嵌入DynamicMBean了.
我们看看下面HelloDynamic程序是如何使用这些原始类构成一个DynamicMBean的:
我们还以上章中的Hello为例,Hello是以Standard MBean来实现了对name的赋值和打印功能.那么通过使用Dynamic
MBean我们也来实现这个功能,在这个资源中,有一个属性name以及操作方法print.下面示例展示如何将这个属性和这个操作方法使用DynamicMBean的原始类来实现:
//
import javax.management.*;
import java.lang.reflect.Constructor;
import java.util.Iterator;
/**
* @author Sunny Peng
* @version 1.0
*/
public class HelloDynamic
implements DynamicMBean {
//这是我们的属性名称
private String name = "";
private MBeanInfo mBeanInfo = null;
private String className = this.getClass().getName();
private String description = "Simple implementation
of a dynamic MBean.";
private MBeanAttributeInfo[] attributes = new MBeanAttributeInfo[1];
private MBeanConstructorInfo[] constructors = new MBeanConstructorInfo[1];
private MBeanOperationInfo[] operations = new MBeanOperationInfo[1];
MBeanNotificationInfo[] mBeanNotificationInfoArray =
new
MBeanNotificationInfo[0];
public HelloDynamic() {
//设定一个属性
attributes[0] = new MBeanAttributeInfo("Name",
"java.lang.String",
"Name: name string.",
true,
true,
false);
//设定构造函数
Constructor[] thisconstructors = this.getClass().getConstructors();
constructors[0] = new MBeanConstructorInfo(
"HelloDynamic(): Constructs a HelloDynamic object",
thisconstructors[0]);
//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);
}
public Object getAttribute(String attribute_name)
{
if (attribute_name.equals("Name"))
return name;
return null;
}
public AttributeList getAttributes(String[] attributeNames)
{
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( (String) attributeNames[i]);
resultList.add(new Attribute(attributeNames[i],
value));
}
catch (Exception e) {
e.printStackTrace();
}
}
return resultList;
}
public void setAttribute(Attribute attribute) {
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 setAttributes(AttributeList attributes)
{
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!");
return null;
}else {
// unrecognized operation name:
throw new ReflectionException(new NoSuchMethodException(
operationName),"Cannot find the operation "
+ operationName + " in " +
className);
}
}
public MBeanInfo getMBeanInfo() {
return mBeanInfo;
}
}
|
编制一个HelloAgent来调用这个HelloDynamic:
// java imports
//
import java.util.*;
import java.io.*;
import java.net.*;
// RI imports
//
import javax.management.ObjectName;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import com.sun.jdmk.comm.HtmlAdaptorServer;
import javax.management.Attribute;
import com.sun.jmx.trace.Trace;
public class HelloAgent {
public HelloAgent() {
}
public static void main(String[] args) {
// CREATE the MBeanServer
//
System.out.println("\n\tCREATE the MBeanServer.");
MBeanServer server = MBeanServerFactory.createMBeanServer();
String domain = server.getDefaultDomain();
ObjectName object_name = null;
//使用HelloDynamic 如果为Hello 就是使用我们上章介绍的StandardMbean了
String mbeanName = "HelloDynamic";
try {
object_name = new ObjectName(domain + ":type="
+ mbeanName);
server.createMBean(mbeanName,object_name);
Attribute stateAttribute = new Attribute("Name","I
am big one");
server.setAttribute(object_name,stateAttribute);
String name = (String) server.getAttribute(object_name,"Name");
System.out.println("name now is "+name);
server.invoke(object_name,"print",null,null);
}
catch (Exception e) {
System.out.println("\t!!! Could not create
the Hello agent !!!");
e.printStackTrace();
return;
}
}
}
|
直接运行HelloAgent就可以在屏幕输出上得到
"Hello ,I am big one, this is from HelloDynamic"
|