从零开始玩转 JMX ( 三 ) — Model MBean

java admin 81200 0 Comment

Model MBean

相对于Standard MBean,Model MBean更加灵活。如果我们不能修改已有的Java类,那么使用Model MBean是不错的选择。

Model MBean也是一种专门化的动态管理构件。它是预制的、通用的和动态的 MBean 类,已经包含了所有必要缺省行为的实现,并允许在运行时添加或覆盖需要定制的那些实现。JMX规范规定该类必须实现为javax.management.modelmbean.RequiredModelMBean,管理者要做的就是实例化该类,并配置该构件的默认行为并注册到JMX代理中,即可实现对资源的管理。JMX代理通过获得一个ModelMBeanInfo对象来获取管理接口。
模型管理构件具有以下新的特点:

  • 持久性。定义了持久机制,可以利用Java的序列化或JDBC来存储模型MBean的状态。 就是要保存到硬盘上。
  • 通知和日志功能。能记录每一个发出的通知,并能自动发出属性变化通知。
  • 属性值缓存。具有缓存属性值的能力。

还是沿用前面的代码,但是这里就不需要类似HelloMBean这样的接口了。

package com.test.jmx.modelBean;

public class Hello { //注意这里没有implements任何东西
private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public void printHello(){
System.out.println("Hello world, "+name);
}

public void printHello(String whoName){
System.out.println("Hello, "+whoName);
}
}

但是需要自己编写一个产生Model MBean的工具类。Model MBean使用JDK提供的RequiredModelMBean,指定基本的Bean(Hello),创建好需要的ModelMBeanInfo就可以了。

package com.test.jmx.modelBean;
import javax.management.*;
import javax.management.modelmbean.*;

/**
 * Created by hidden on 2016/10/9.
 */
public class ModelMBeanUtils {
private static final boolean READABLE = true;
private static final boolean WRITABLE = true;
private static final boolean BOOLEAN = true;
private static final String STRING_CLASS = "java.lang.String";
public static RequiredModelMBean createModelerMBean() {
RequiredModelMBean model = null;
try {


model = new RequiredModelMBean();


model.setManagedResource(new Hello(), "ObjectReference");


ModelMBeanInfo info = createModelMBeanInfo();


model.setModelMBeanInfo(info);
} catch (Exception e) {


e.printStackTrace();
}
return model;
}
private static ModelMBeanInfo createModelMBeanInfo() {
//////////////////////////////////////////////////////////////////
//



属性



//
//////////////////////////////////////////////////////////////////
// 构造name属性信息
Descriptor portAttrDesc = new DescriptorSupport();
portAttrDesc.setField("name", "Name");
portAttrDesc.setField("descriptorType", "attribute");
portAttrDesc.setField("displayName", "Name");
portAttrDesc.setField("getMethod", "getName");
portAttrDesc.setField("setMethod", "setName");
ModelMBeanAttributeInfo nameAttrInfo = new ModelMBeanAttributeInfo(//


"Name", // 属性名


STRING_CLASS, //属性类型


"people name", // 描述文字


READABLE, WRITABLE, !BOOLEAN, // 读写


portAttrDesc // 属性描述
);
//////////////////////////////////////////////////////////////////
//



方法



//
//////////////////////////////////////////////////////////////////
// 构造 getName操作描述符信息
Descriptor getStateDesc = new DescriptorSupport(new String[] {


"name=getName",


"descriptorType=operation",


"class=com.test.jmx.modelBean.Hello",


"role=operation"
});

ModelMBeanOperationInfo getName = new ModelMBeanOperationInfo(//


"getName", //


"get name attribute", //


null, //


"java.lang.String", //


MBeanOperationInfo.ACTION, //


getStateDesc //
);

// 构造 setName操作描述符信息
Descriptor setStateDesc = new DescriptorSupport(new String[] {


"name=setName", "descriptorType=operation", "class=com.test.jmx.modelBean.Hello",


"role=operation" });

MBeanParameterInfo[] setStateParms = new MBeanParameterInfo[] { (new MBeanParameterInfo(


"name", "java.lang.String", "new name value")) };

ModelMBeanOperationInfo setName = new ModelMBeanOperationInfo(//


"setName", //


"set name attribute", //


setStateParms, //


"void", //


MBeanOperationInfo.ACTION, //


setStateDesc //
);

//构造 printHello()操作的信息
ModelMBeanOperationInfo print1Info = new ModelMBeanOperationInfo(//


"printHello", //


null, //


null, //


"void", //


MBeanOperationInfo.INFO, //


null //
);
// 构造printHello(String whoName)操作信息
ModelMBeanOperationInfo print2Info;
MBeanParameterInfo[] param2 = new MBeanParameterInfo[1];
param2[0] = new MBeanParameterInfo("whoName", STRING_CLASS, "say hello to who");
print2Info = new ModelMBeanOperationInfo(//


"printHello", //


null,//


param2,//


"void", //


MBeanOperationInfo.INFO, //


null//
);
//////////////////////////////////////////////////////////////////
//



最后总合



//
//////////////////////////////////////////////////////////////////
// create ModelMBeanInfo
ModelMBeanInfo mbeanInfo = new ModelMBeanInfoSupport(//


RequiredModelMBean.class.getName(), // MBean类


null, // 描述文字


new ModelMBeanAttributeInfo[] { // 所有的属性信息(数组)


nameAttrInfo },//只有一个属性


null, // 所有的构造函数信息


new ModelMBeanOperationInfo[] { // 所有的操作信息(数组)


getName,


setName,


print1Info,


print2Info },//


null, // 所有的通知信息(本例无)


null//MBean描述
);
return mbeanInfo;
}
}

这里着重说明下ModelMBeanInfo接口
编写Model MBean的最大挑战是告诉Model MBean对象托管资源的那些熟悉和方法可以暴露给代理。ModelMBeanInfo对象描述了将会暴露给代理的构造函数、属性、操作甚至是监听器。
创建了ModelMBeanInfo对象后,需要将其与ModelMBean对象关联。目前有两种方式可以做到这一点:

  • 传入ModelMBeanInfo对象给RequiredModelMBean对象的构造函数。
  • 调用RequiredModelMBean对象的setModelMBeanInfo方法。

创建了ModelMBean对象后(RequiredModelMBean implements ModelMBean),需要调用ModelMBean接口的setManagedResource()方法将其与托管资源关联,该方法如下:

public void setManagedResource(Object managedResource, String managedResourceType) ;

managedResourceType的值可以为ObjectReference, Handle, IOR, EJBHandle或RMIReference,但当前只支持ObjectReference.

在注册时没有什么特别之处,只是需要注意下通过工具类获得MBean即可

package com.test.jmx.modelBean;

import com.sun.jdmk.comm.HtmlAdaptorServer;

import javax.management.*;
import javax.management.modelmbean.RequiredModelMBean;
import java.lang.management.ManagementFactory;

public class HelloAgent {
public static void main(String[] args) throws MalformedObjectNameException, NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();

ObjectName helloName = new ObjectName("MyMBean:name=HelloWorld");
//Hello hello = new Hello();
RequiredModelMBean hello = ModelMBeanUtils.createModelerMBean();
server.registerMBean(hello, helloName);

ObjectName adapterName = new ObjectName("MyMBean:name=htmladapter,port=8082");
HtmlAdaptorServer adapter = new HtmlAdaptorServer();
server.registerMBean(adapter, adapterName);
adapter.start();
}
}

运行结果:略。

Model MBean可以动态配置。试想一下这个应用场景:由于安全或其他原因,系统要把某个MBean公开的可管理方法隐藏起来。这时,如果你是用标准MBean,这需要修改接口类,然后重新编译发布;如果用 Apache commons-modeler(如果不想总要维护MBean这个借口,那么可以使用Apache的commons-modeler来辅助开发MBean,所有的MBean都装配在XML文件中)来写的模型MBean,则只需要修改XML文件就行了,不需要重新编译发布(可能要重启一下系统)。这就是Model Mbean 优势之所在了。

参考资料

Reproduced please indicate the source: 飞嗨_分享互联网 » 从零开始玩转 JMX ( 三 ) — Model MBean

Like (0) or Share (0)
Guest Post my comment   Change account
Cancel comment

emoj
(0)person posted

Effective,Professional,Conform to SEO

Contact us