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 优势之所在了。


参考资料

  1. JMX整理
  2. JMX简介
  3. http://blog.csdn.net/DryKillLogic/article/category/762777
  4. 用Apache的commons-modeler来辅助开发JMX

从零开始玩转JMX(三)——Model MBean的更多相关文章

  1. 从零开始玩转JMX(四)——Apache Commons Modeler & Dynamic MBean

    Apache Commons Modeler 前面的Model MBean的创建方式看上去特别复杂,一个简单功能的类ModelMBeanUtils 写了很多代码,那有木有简单点的方式呢,答案是肯定的, ...

  2. 从零开始玩转JMX(一)——简介和Standard MBean

    JMX的全称为Java Management Extensions. 顾名思义,是管理Java的一种扩展.这种机制可以方便的管理.监控正在运行中的Java程序.常用于管理线程,内存,日志Level,服 ...

  3. 从零开始玩转JMX(二)——Condition

    Notification 一个MBean提供的管理接口允许代理对其管理资源进行控制和配置.然而,对管理复杂的分布式系统来说,这些接口知识提供了一部分功能.通常,管理应用程序需要对状态变化或者当特别情况 ...

  4. 从零开始学Xamarin.Forms(三) Android 制作启动画面

    原文:从零开始学Xamarin.Forms(三) Android 制作启动画面     Xamarin.Forms 在启动的时候相当慢,必须添加一个启动界面,步骤如下: 1.将启动画面的图片命名为:s ...

  5. 微信小程序从零开始开发步骤(三)底部导航栏

    上一章节,我们分享了如何创建一个新的页面和设置页面的标题,这一章我们来聊聊底部导航栏是如何实现的.即点击底部的导航,会实现不同对应页面之间的切换. 我们先来看个我们要实现的底部导航栏的效果图:(三个导 ...

  6. 从零开始使用git第三篇:git撤销操作、分支操作和常见冲突

    从零开始使用git 第三篇:git撤销操作.分支操作和常见冲突 第一篇:从零开始使用git第一篇:下载安装配置 第二篇:从零开始使用git第二篇:git实践操作 第三篇:从零开始使用git第三篇:gi ...

  7. 从零开始学习MXnet(三)之Model和Module

    在我们在MXnet中定义好symbol.写好dataiter并且准备好data之后,就可以开开心的去训练了.一般训练一个网络有两种常用的策略,基于model的和基于module的.今天,我想谈一谈他们 ...

  8. Excel应该这么玩——5、三种数据:Excel也是系统

        Excel最常用的功能就是记录数据,把数据按照行列记录下来.这部分数据是源数据,是业务活动中最原始的流水账,作为后续操作的依据.为了从源数据中得出一定的结论,需要对源数据进行分析得出报表数据. ...

  9. SQL Server调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行)

    前言 本篇继续玩转模块的内容,关于索引在SQL Server的位置无须多言,本篇将分析如何利用Hint引导语句充分利用索引进行运行,同样,还是希望扎实掌握前面一系列的内容,才进入本模块的内容分析. 闲 ...

随机推荐

  1. 巨蟒python全栈开发-第11阶段 devops-git&&openpyxl2

    大纲 1.git分支 2.git tag 3.git 忽略文件 4.正则表达式 5.openpyxl写数据 6.openpyxl读数据 1.git分支 2.git tag 3.git 忽略文件 4.正 ...

  2. 干货 | 蚂蚁金服是如何实现经典服务化架构往 Service Mesh 方向的演进的?

    干货 | 蚂蚁金服是如何实现经典服务化架构往 Service Mesh 方向的演进的? https://www.sohu.com/a/235575064_99940985 干货 | 蚂蚁金服是如何实现 ...

  3. C++之贪吃蛇

    #include<iostream> #include<cstdio> #include<cstdlib> #include<ctime> #inclu ...

  4. 基于rman的坏块恢复

    转载请注明出处 http://blog.csdn.net/guoyjoe/article/details/30965303   实验过程例如以下: 1.使用rman备份全库 Recovery Mana ...

  5. 18.让sublime text3支持Vue语法高亮显示

    1.准备语法高亮插件vue-syntax-highlight. 下载地址: https://github.com/vuejs/vue-syntax-highlight 下载页面并下载: 解开压缩包vu ...

  6. 【开发者笔记】冒泡排序过程呈现之java内置GUI表示

    自己玩玩写写,排序的过程多么有趣,特别是把看着电脑吧一堆乱七八糟的数据排成有序组合的时候,看起来贼舒服,特别是强迫症患者.好了,话不多说上代码,也算是自己记录一下吧,没有什么技术含量但个人感觉比较有趣 ...

  7. HDU1115&&POJ1385Lifting the Stone(求多边形的重心)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1115# 大意:给你个n,有n个点,然后给你n个点的坐标,求这n个点形成的多边形的重心的坐标. 直接套模 ...

  8. Java中树的存储结构实现

    一.树 树与线性表.栈.队列等线性结构不同,树是一种非线性结构. 一棵树只有一个根节点,如果一棵树有了多个根节点,那它已经不再是一棵树了,而是多棵树的集合,也被称为森林. 二.树的父节点表示法 树中除 ...

  9. HMM,MEMM,CRF模型的比较

    本文参考自:http://blog.csdn.net/happyzhouxiaopei/article/details/7960876 这三个模型都可以用来做序列标注模型.但是其各自有自身的特点,HM ...

  10. 元类 metaclass

    metaclass 类由Type创建 对象由创建 MetaClass作用 用来指定当前类由谁来创建(默认type创建). MetaClass 会被继承,如果父类指定了元类,那么子类也是由这个元类创建 ...