【JMX】3. 动态MBean

复习

一共有四种MBean:

  1. 标准MBeans(Standard MBeans)设计和实现是最简单的,这类MBean使用自己的方法名作为管理接口;——在前一篇中的Hello、HelloMBean就是一个标准MBeans(Standard MBeans)
  2. 动态MBeans(Dynamic MBeans)必须实现一个指定的接口,由于动态MBeans在运行期间暴露它们的管理接口,因此更为灵活;
  3. 开放MBeans(Open MBeans)属于动态MBeans,这类MBean依靠基础数据类型来实现通用管理,并为友情用户进行自我声明;
  4. 模型MBeans(Model MBeans)同样也是动态MBeans,这类MBeans是完全可配置的,在运行期间进行自我声明;它们为资源动态工具提供一个一般性的,有默认行为的MBeans类。

动态MBean是在运行期才定义它的属性和方法,也就是说它有什么属性和方法是可以动态改变的。

动态MBean主要利用一些辅助类(构造函数类MBeanConstructorInfo、属性类MBeanAttributeInfo、方法类MBeanOperationInfo)来完成这个功能,所有的动态MBean必须实现DynamicMBean接口。

DynamicMBean写好后,使用方法和第一篇文章中普通的MBean一样。


1)编写动态MBean

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.", //String description,
        		true, true, false);   //boolean isReadable,boolean isWritable,boolean isIs

        //operate method 我们的操作方法是print   
        MBeanParameterInfo[] params = null;//无参数   
        operations[0] = new MBeanOperationInfo(
        		"print", 
        		"print(): print the name", //String description,
        		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);   
    }   
  
    @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 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();   
        }   
    }   
    @Override
    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;   
    }   
    @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 operation name and call the corresponding operation   
        if (operationName.equals("print")) {   
            //=======具体实现我们的操作方法print =======
            System.out.println("Hello, " + name + ", this is HellDynamic!");   
            dynamicAddOperation();   
            System.out.println("added a dynamic operation(print1)!");
            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);   
        }   
  
    }   
  
    @Override
	public MBeanInfo getMBeanInfo() {   
        return mBeanInfo;   
    }   
}   

2)编写Agent

前面说了HelloDynamic和普通MBean的使用方法是一样的,因此HelloAgent和第一篇的HelloAgent基本一样,就是把Hello改成HelloDynamic而已。

public class HelloAgent {
	 public static void main(String[] args) throws Exception { 
	    	
	    	//先创建了一个MBeanServer,用来做MBean的容器
//	    	MBeanServer server = MBeanServerFactory.createMBeanServer();   
	        MBeanServer server = ManagementFactory.getPlatformMBeanServer();   
	        ObjectName helloName = new ObjectName("alpha-dynamic:name=HelloWorld");  
	        HelloDynamic hello=new HelloDynamic();   
	        //将Hello这个类注入到MBeanServer中,注入需要创建一个ObjectName类
	        server.registerMBean(hello, helloName);   
	        
	        //创建一个AdaptorServer,这个类将决定MBean的管理界面,这里用最普通的Html型界面。AdaptorServer其实也是一个MBean。
	        // alpha:name=HelloWorld的名字是有一定规则的,格式为:“域名:name=MBean名称”,域名和MBean名称都可以任意取。
	        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方法。

start.....
Hello, null, this is HellDynamic!
added a dynamic operation(print1)!
这是动态增加的一方法print1

4)总结

动态MBean的代码稍显复杂,但对于一些特殊需求的情况,它将显示出强大威力。而且它还是模型MBeans(Model MBeans)的基础。不过在一般的项目中,动态MBean还是用得比较少,所谓利器深藏之而不用,非常时方现光芒。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值