JMX之Dynamic MBean

JMX的Dynamic MBean不需要自定义MBean接口,只需要实现JDK提供的DynamicMBean接口即可。Dynamic MBean没有任何明显写在代码里的属性和方法,所有的属性和方法都是通过反射结合JMX提供的辅助元数据,从而动态生成的。

Dynamic MBean:

package com.jmx.dynamic.demo;

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;

public class HelloDynamic implements DynamicMBean {
	
	//attributes
	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 MBean.";   
		
		//initial attributes
		attributes = new MBeanAttributeInfo[1];   
		//initial constructors
		constructors = new MBeanConstructorInfo[1];
		//initial method
		operations = new MBeanOperationInfo[1];   
		
		mBeanNotificationInfoArray = new MBeanNotificationInfo[0];   
	}   
 
	private void buildDynamicMBean() {   
		//create constructor   
		Constructor[] thisconstructors = this.getClass().getConstructors();   
		constructors[0] = new MBeanConstructorInfo("HelloDynamic(): Constructs a HelloDynamic object", thisconstructors[0]);   
		
		//create attribute   
		attributes[0] = new MBeanAttributeInfo("Name", "java.lang.String", "Name: name string.", true, true,false);   
		
		//create operate method
		MBeanParameterInfo[] params = null;//no parameter
		operations[0] = new MBeanOperationInfo("print", "print(): print the name", params, "void", MBeanOperationInfo.INFO);    
		
		//create mbean
		mBeanInfo = new MBeanInfo(className, description, attributes, constructors, operations, mBeanNotificationInfoArray);   
	}   
	
	//dynamically add a print1 method
	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);   
	}   
	
	@Override
	public Object getAttribute(String attribute_name) {
		if (attribute_name == null) {
			return null;
		}
		
		if (attribute_name.equals("Name")) {
			return name;
		}
		
		return null;
	}   

	@Override
	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 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();   
		}   
	}   

	@Override
	public AttributeList getAttributes(String[] attributeNames) {   
		if (attributeNames == null) {
			return null;
		}
		
		AttributeList resultList = new AttributeList();   
		// if attributeNames is empty, return anempty 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;   
	}   

	@Override
	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;   
		}   
	
	@Override
	public Object invoke(String operationName, Object params[], String signature[]) throws MBeanException,ReflectionException {   
		// Check for a recognized operationname and call the corresponding operation   
		if (operationName.equals("print")) { 
			System.out.println("Hello, " + name + ", this is HelloDynamic!");  
			
			//dynamic add a method
			dynamicAddOperation();   
			return null;   
		} else if (operationName.equals("print1")) {   
			System.out.println("dynamically add a print1 method");   
			return null;   
		} else {   
			// unrecognized operation name:
			throw new ReflectionException(new NoSuchMethodException(operationName), "Cannot find the operation " + operationName + " in " + className);   
		}   

	}   

	public MBeanInfo getMBeanInfo() {   
		return mBeanInfo;   
	}
}

通过Agent调用Dynamic MBean,方式和Standard MBean相同

package com.jmx.dynamic.demo;

import java.lang.management.ManagementFactory;

import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;

import com.sun.jdmk.comm.HtmlAdaptorServer;

public class HelloAgent {//as same as standard mbean
	public static void main(String[] args) throws MalformedObjectNameException, NullPointerException, InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
		
		//create mbean server
		MBeanServer server = ManagementFactory.getPlatformMBeanServer();
		
		//create object name
		ObjectName helloName = new ObjectName("jmx:name=dynamicBeanHello");
		
		//create mbean and register mbean
		server.registerMBean(new HelloDynamic(), helloName);
		
		//create adaptor, adaptor is just a form as show mbean. It has no relation to specific mbean.
		HtmlAdaptorServer adaptor  = new HtmlAdaptorServer();
		//create adaptor name
		ObjectName adaptorName = new ObjectName("jmxAdaptor:name=adaptor,port=5050");
		//register adaptor and adaptor name
		server.registerMBean(adaptor, adaptorName);
		
		adaptor.setPort(9999);
		adaptor.start();
		System.out.println("....................jmx server start....................");
	}
}

启动JMX服务,访问http://localhost:9999/

点击我们在JMXServer上注册的Dynamic MBean


可以看到动态生成的属性和方法:

JMX之Dynamic MBean_第1张图片

点击print方法后,控制台输出如下:


再返回MBean View,可以看到又动态创建了一个print1方法:

JMX之Dynamic MBean_第2张图片




Dynamic MBean应用的场景并不多,正所谓:利器深藏之而不用,非常时方现光芒。

你可能感兴趣的:(J2ee)