• 浅谈JMX


    JMX在Java编程语言中定义了应用程序以及网络管理和监控的体系结构、设计模式、应用程序接口以及服务。通常使用JMX来监控系统的运行状态或管理系统的某些方面,比如清空缓存、重新加载配置文件等
    优点是可以非常容易的使应用程序被管理
    伸缩性的架构使每个JMX Agent服务可以很容易的放入到Agent中,每个JMX的实现都提供几个核心的Agent服务,你也可以自己编写服务,服务可以很容易的部署,取消部署。
    主要作用是提供接口,允许有不同的实现。
      如果一个java对象可以由一个遵循JMX规范的管理器应用程序管理,那么这个java对象称为一个可由JMX管理的资源。实际上一个可由JMX管理的资源可以是一个应用程序、一种实现、一个服务、一个设备、一个用户等,一个可由JMX管理的资源也是由java编写。并提供了一个相应的java包装。
      若要使一个java对象成为一个可由JMX管理的资源,则必须创建一个名为Managed Bean或者 MBean的对象,MBean会提供它所管理的一些java对象的属性和方法供管理应用程序使用,管理应用程序本身并不能直接访问托管的java对象,因此,需要选择托管的java对象的那些属性可以由管理应用程序使用。
      当拥有了一个MBean类之后,需要将其实例化,并将其注册到另一个作为MBean服务器的java对象中,MBean服务器中保存了应用程序中注册的所有MBean,管理应用程序通过MBean服务器来访问MBean实例,可以将JMX与Servlet应用程序做一个类比,管理应用程序的作用类似于Web浏览器,MBean服务器 的作用类似于Servlet容器,MBean服务器提供了使管理应用程序可以访问托管资源的方法。MBean实例就好比Servlet类或者Jsp页面,Web浏览器无法直接访问servlet实例或JSP页面,必须要通过Servlet容器才可以,管理应用程序也必须要通过MBean服务器来访问MBean实例。
      共有四种类型的MBean,分别为标准类型、动态类型、开放类型、和模型类型,其中标准类型的MBean最容易编写,但是灵活性最低,其他三种类型的灵活性较好,其中我们对模型MBean感兴趣,因为Catalina中就使用了这种类型的MBean。
      从结构上将,JMX规范分为三层:设备层、代理层和分布式服务层,MBean服务器位于代理层,MBean位于设备层,分布式服务层会在JMX规范将来的版本中涉及。
      设备层规范定义了编写可由JMX管理的资源的标准,即如何编写MBean,代理层定义了创建代理的规范,代理封装了MBean服务器,提供了处理MBean的服务。代理和它所管理的MBean通常都位于同一个java虚拟机中,由于JMX规范附带了一个参考实现,因此并不需要自己编写MBean服务器。

      MBeanServer类

      MBean服务器是javax.management.MBeanServer接口的实例,要创建一个MBeanServer实例。只需要调用javax.management.MBeanServerFactory类的createMBean()方法即可。

      要将一个MBean注册到MBean服务器中,可以调用MBeanServer实例的registerMBean()方法,下面是registerMBean方法的签名;

    ObjectInstance registerMBean(java.lang.Object object, ObjectName var2)
                throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException;

    要调用registerMBean方法,需要传入一个待注册的MBean实例(就是第一个参数)和一个ObjectName实例,ObjectName实例与HashMap中的键类似,它可以唯一地标识一个MBean实例。registerMBean方法会返回一个ObjectInstance实例。javax.management.ObjectInstance类封装了一个MBean实例的对象名称和它的类名。

      要想获取MBean实例或匹配某个模式的一组MBean实例。可以使用MBeanServer接口提供的两个方法,分别是queryNames方法 和 queryMBeans方法,queryNames方法返回一个java.util.Set实例,其中包含了匹配某个指定模式对象名称的一组MBean实例的对象名称,下面是queryNames方法的签名:

    java.util.Set queryNames(ObjectName name, QueryExp query);

    其中 query制定了过滤条件,若参数name为null 或者没有域,而且指定了key属性,name返回应注册的MBean实例的所有ObjectName实例,如果参数query为null,则不会对查找对象进行过滤。

      queryMBeans方法与queryNames方法类似,它返回的也是一个java.util.Set实例,但是其中包含的是被选择的Mbean实例的ObjectInstance对象,queryMBean方法的签名如下:

    java.util.Set queryMBeans(ObjectName name, QueryExp query);

      一旦获得了所需要MBean实例对象名称,就可以操作托管资源在MBean实例中提供的属性或调用其方法,

      可以通过调用MBeanServer接口的invoke方法调用已经注册的MBean实例的任何方法,MBeanServer接口的getAttribute方法 和 setAttribut方法用于获取或设置已经注册的MBean实例的属性。

    ObjectName类

      MBean实例注册于MBean服务器中,MBean服务器中的每一个MBean实例都通过一个对象名称来唯一标识,就好像是HashMap中的每一个条目都通过一个键来唯一的标识一样。

      对象名称是javax.managerment.ObjectName类的实例,对象名称由两部分组成,域和一个键/值对。域是一个字符串,也可以是空字符串,在对象名称中,域后接一个分号,然后是一个或者多个键/值对,在键/值对重,键(key)是一个非空字符串,并且不能包含下列字符:等号、逗号、分号、星号、和问号。在一个对象名称中,同一个键只能出现一次,

      键与其值是由等号分隔的,键/值对之间用逗号号分隔。例如下面是一个有效的对象名称,其中包含两个键:

    myDomain:type=Car,color=blue
    域:key=value,key = value

    ObjetName实例也表示在MBean服务器中搜索MBean实例的属性模式,ObjectName实例可以在 域 部分或者 键值对 部分使用通配符来表示模式,作为模式的ObjectName可以有 0 个或多个键。

    标准MBean

      标准MBean是最简单的MBean类型,要想通过标准MBean来管理一个java对象,需要执行以下步骤。

    1. 创建一个接口,该接口的命名规范为:java类名+MBean后缀。例如,如果想要管理的java类名为Car,则需要创建的接口命名为CarMBean;
    2. 修改java类,让其实现刚刚创建的CarMBean接口。
    3. 创建一个代理,该代理类必须包含一个MbeanServer实例。
    4. 为Mbean创建ObjectName实例;
    5. 实例化MBeanServer类,
    6. 将MBean注册到MBeanServer中;

      标准MBean是最容易编写的MBean类型,但是用标准MBean就必须要修改原有的java类,在某些项目中,这不是问题,但是在其他一些项目(尤其是很多类的项目)中,这是不可以接受的,其他类型的MBean允许在不修改原有java类的基础上管理java对象,

    下面是一个标准MBean的例子,其中假设你想要使其成为JMC可管理的类是Car,

    第一步 先创建一个符合命名规范的接口

     1 package myex20.pyrmont.Standardmbeantest;
     2 
     3 /**
     4  * <p>
     5  * <b>Title:CarMBean.java</b>
     6  * </p>
     7  * <p>
     8  * Copyright:ChenDong 2018
     9  * </p>
    10  * <p>
    11  * Company:仅学习时使用
    12  * </p>
    13  * <p>
    14  * 类功能描述:要管理Car类的标准MBean接口
    15  * 创建一个接口,该接口的命名规范为:java类名+MBean后缀。例如,如果想要管理的java类名为Car,则需要创建的接口命名为CarMBean;
    16  * </p>
    17  * <p>
    18  * 基本上来讲,要在接口中声明Car类中的所要提供的所有方法,在这个例子中,在CarMBean接口中生命了Car类的所有方法,如果不希望Car类的drive方法在管理应用程序中调用,
    19  * 只需要将drive方法的定义从CarMBean中移除即可。
    20  * </p>
    21  * 
    22  * @author 陈东
    23  * @date 2018年12月4日 下午7:36:50
    24  * @version 1.0
    25  */
    26 public interface CarMBean {
    27     public String getColor();
    28 
    29     public void setColor(String color);
    30 
    31     public void drive();
    32 
    33 }

    然后让我们想要被管理的原java类 也就是 Car类实现该接口

     1 package myex20.pyrmont.Standardmbeantest;
     2 
     3 /**
     4  * <p>
     5  * <b>Title:Car.java</b>
     6  * </p>
     7  * <p>
     8  * Copyright:ChenDong 2018
     9  * </p>
    10  * <p>
    11  * Company:仅学习时使用
    12  * </p>
    13  * <p>
    14  * 类功能描述:
    15  * </p>
    16  * 
    17  * @author 陈东
    18  * @date 2018年12月4日 下午7:34:25
    19  * @version 1.0
    20  */
    21 public class Car implements CarMBean {
    22     private String color = "red";
    23 
    24     public String getColor() {
    25         return color;
    26     }
    27 
    28     public void setColor(String color) {
    29         this.color = color;
    30     }
    31 
    32     public void drive() {
    33         System.out.println("Baby you can drive my*" + color + "*car.");
    34     }
    35 }

    然后创建一个代理类 包含一个 MBeanServer类的实例 来管理 Mbean

      1 package myex20.pyrmont.Standardmbeantest;
      2 
      3 import javax.management.Attribute;
      4 import javax.management.AttributeNotFoundException;
      5 import javax.management.InstanceAlreadyExistsException;
      6 import javax.management.InstanceNotFoundException;
      7 import javax.management.InvalidAttributeValueException;
      8 import javax.management.MBeanException;
      9 import javax.management.MBeanRegistrationException;
     10 import javax.management.MBeanServer;
     11 import javax.management.MBeanServerFactory;
     12 import javax.management.NotCompliantMBeanException;
     13 import javax.management.ObjectName;
     14 import javax.management.ReflectionException;
     15 
     16 /**
     17  * <p>
     18  * <b>Title:StandardAgent.java</b>
     19  * </p>
     20  * <p>
     21  * Copyright:ChenDong 2018
     22  * </p>
     23  * <p>
     24  * Company:仅学习时使用
     25  * </p>
     26  * <p>
     27  * 类功能描述: 代理类用来实例化MBean服务器,并使用MBean服务器注册CarBean实例。首先要注意的是变量
     28  * MBeanServer,StandardAgent类的构造函数会将一个MBeanServer实例赋值给变量MBeanServer。
     29  * 构造函数会调用MBeanServerFactory类的createMBeanServer方法 创建一个MBeanServer实例,
     30  * createMBeanServer方法
     31  * 会返回JMX参考实现的一个默认的MBeanServer对象。资深JMX程序员可能会实现自己的MBeanServer,
     32  * </p>
     33  * * @author 陈东
     34  * 
     35  * @date 2018年12月4日 下午7:44:13
     36  * @version 1.0
     37  */
     38 public class StandardAgent {
     39     /**
     40      * 管理MBean的服务器实例
     41      */
     42     private MBeanServer mBeanServer = null;
     43 
     44     /**
     45      * 
     46      * 
     47      * <p>
     48      * Title:无参数构造器
     49      * </p>
     50      * 
     51      * <p>
     52      * Description: 使用默认构造创建一个新的{@code StandardAgent }实例
     53      * </p>
     54      */
     55     public StandardAgent() {
     56         // 使用MBeanServerFactory工程类 创建MBeanServer实例
     57         mBeanServer = MBeanServerFactory.createMBeanServer();
     58     }
     59 
     60     /**
     61      * 
     62      * 
     63      * <p>
     64      * Title: getMBeanServer
     65      * </p>
     66      * 
     67      * @date 2018年12月4日 下午7:51:31
     68      * 
     69      *       <p>
     70      *       功能描述: 获取代理类中的MBeanServer实例
     71      *       </p>
     72      * 
     73      * @return
     74      */
     75     public MBeanServer getMBeanServer() {
     76         return mBeanServer;
     77     }
     78 
     79     /**
     80      * 
     81      * 
     82      * <p>
     83      * Title: createObjectName
     84      * </p>
     85      * 
     86      * @date 2018年12月4日 下午7:55:07
     87      * 
     88      *       <p>
     89      *       功能描述: 根据指定的name属性来创建 {@code ObjectName} 实例
     90      *       </p>
     91      * 
     92      * @param name
     93      * @return
     94      */
     95     public ObjectName createObjectName(String name) {
     96         ObjectName objectName = null;
     97         try {
     98             objectName = new ObjectName(name);
     99         } catch (Exception e) {
    100             e.printStackTrace();
    101         }
    102         return objectName;
    103 
    104     }
    105 
    106     /**
    107      * 
    108      * 
    109      * <p>
    110      * Title: createStandardBean
    111      * </p>
    112      * 
    113      * @date 2018年12月4日 下午8:09:01
    114      *       <p>
    115      *       功能描述: 方法中会调用MBeanServer实例的createMBean方法,createMBean方法接收托管资源的类名,
    116      *       和一个ObjectName实例,该ObjectName实例
    117      *       唯一的表示了为托管资源创建的MBean实例,creatMBean方法也会将创建的MBean实例注册到MBean
    118      *       服务器中。由于标准MBean实例遵循了特定的命名规则,因此不需要
    119      *       为createMbean方法提供MBean的类名,如果托管资源的类名是Car,则创建的MBean的类名为CarMBean。
    120      *       </p>
    121      * 
    122      * 
    123      * @param objectName
    124      * @param managedResourceClassName
    125      */
    126     @SuppressWarnings("unused")
    127     private void createStandardBean(ObjectName objectName, String managedResourceClassName) {
    128         try {
    129             mBeanServer.createMBean(managedResourceClassName, objectName);
    130         } catch (InstanceAlreadyExistsException e) {
    131             // TODO Auto-generated catch block
    132             e.printStackTrace();
    133         } catch (NotCompliantMBeanException e) {
    134             // TODO Auto-generated catch block
    135             e.printStackTrace();
    136         } catch (MBeanRegistrationException e) {
    137             // TODO Auto-generated catch block
    138             e.printStackTrace();
    139         } catch (MBeanException e) {
    140             // TODO Auto-generated catch block
    141             e.printStackTrace();
    142         } catch (ReflectionException e) {
    143             // TODO Auto-generated catch block
    144             e.printStackTrace();
    145         }
    146 
    147     }
    148 
    149     public static void main(String[] args) {
    150         // 创建一个代理类的实例
    151         StandardAgent agent = new StandardAgent();
    152         // 获取一个MBeanServer 的引用
    153         MBeanServer mBeanServer = agent.getMBeanServer();
    154 
    155         /**
    156          * 为我们要管理的CarBean实例
    157          * 创建一个ObjectName对象,MBeanServer实例的默认域会作为ObjectName实例的域使用。
    158          * 一个名为type的键会被添加到域的后面,键type的值是托管资源的完全限定名;
    159          */
    160         // 获取 MBeanServer实例的默认域
    161         String domain = mBeanServer.getDefaultDomain();
    162         // 被托管资源java类的完全限定名 不是对应的MBean包装类
    163         String managedResourceClassName = "myex20.pyrmont.Standardmbeantest.Car";
    164         // 然后创建ObjectName对象
    165         ObjectName oname = agent.createObjectName(domain + ":type=" + managedResourceClassName);
    166         // 调用 agent的 createStandardMBean方法,并传入创建好的 对象名称对象 和 托管资源java类的 类限定名
    167         // 接着 就会调用MBeanServer的 creatMBean来创建并管理
    168         // CarMBean,也就是通过CarMBean实例来管理Car对象。
    169         agent.createStandardBean(oname, managedResourceClassName);
    170         // 创建一个名为 colorattribute的Attribute类型的对象,用来表示Car类的color属性,并设置其值 为blue,
    171         Attribute colorattribute = new Attribute("Color", "blue");
    172         // 然后 用MBean 服务器对象的setAttribute方法,传入代表 CarMBean 的ObjectName 对象 与 为
    173         // CarBean管理的Car设置的Attitude对象
    174         try {
    175             mBeanServer.setAttribute(oname, colorattribute);
    176             System.out.println(mBeanServer.getAttribute(oname, "Color"));
    177             mBeanServer.invoke(oname, "drive", null, null);
    178         } catch (InstanceNotFoundException | InvalidAttributeValueException | AttributeNotFoundException
    179                 | ReflectionException | MBeanException e) {
    180 
    181             e.printStackTrace();
    182         }
    183 
    184     }
    185 
    186 }

    剩余步骤大家看 上面代码吧 ,不想再写啦哈。

    从上面的例子我们可以看到,我们已经可以通过StandardAgent类来直接访问Car对象了,但是这里的关键问题是可以选择那些功能要暴露出来,那些方法需要对外隐藏。

    模型MBean

      相对于标准MBean,模型MBean更具有灵活性,在编程上,模型MBean难度更大一些,但是也不需要为可管理的对象修改原java类了,如果不能修改已有的java类,那么使用模型MBean是一个不错的选择。

      使用模型MBean与使用标准MBean有一些区别,在使用标准MBean来管理资源时,需要定义一个接口,然后让托管资源实现该接口,而使用模型MBean时,不需要定义接口,相反是可以使用javax.management.modelmbean.ModelMBean接口来表示模型MBean

    ,只需要实现该接口,在JMX的参考实现中,有一个javax.management.modelmbean.RequiredModelMBean类,是ModelMBean接口的默认实现,可以实例化RequiredModelMBean类或者其子类,也可以使用ModelMBean接口的其他实现类。

     编写一个模型MBean的最大挑战是告诉ModelMBean对象托管资源的那些属性和方法可以暴露给代理,可以通过创建 javax.management,modelmbean.ModelMBeanInfo对象来完成这个任务,ModelMBeanInfo对象描述了将会暴露给代理的构造函数、属性、操作、甚至是监听器。创建ModelMBeanInfo对象是一件特别枯燥的事情,但当创建了该实例后,只需要将其与ModelMBean对象相关联即可。

     使用RequiredModelMBean类作为ModelMBean的实现,有两种方式可以将ModelMBeanInfo对象相关联;

    1. 传入一个ModelMBeanInfo对象到 RequiredModelMBean对象的构造函数中
    2. 调用RequiredModelMBean类的setModelMBeanInfo方法,并传入一个ModelMBean对象

      在创建了ModelMBean对象之后,需要调用ModelMbean接口的setManagedResource方法将 ModelMBean与其托管的资源相互关联,该方法的签名如下

    public void setManagedResource(java.lang.Object managedResource, java.lang.String managedResourceType) throws MBeanException, RuntimeOperationsException, InstanceNotFoundException, InvalidTargetObjectTypeException ;

    字符串参数 managedResourceType的值只可以是下面之一:ObjectReference、Handle、IOR、EJBHandle或者RMIReference。当前只支持ObjectReference。

      还需要创建一个ObjectName实例,并将MBean实例注册到MBean服务器中,下面先介绍一下ModelMBeanInfo接口,该接口的实例会将托管资源的属性 和方法提供给代理层。

    MBeanInfo 接口 与 ModelMBeanInfo接口

      javax.management,mbean.ModelMBeanInfo接口描述了要通过ModelMBean暴露给代理层的构造函数、属性、方法、和监听器,其中 构造函数是  javax.management.modelmbean.ModelMBeanConstructorInfo类的实例,属性是javax.management.modelmbean.ModelMBeanAttributeInfo类的实例,方法是javax.management.modelmbean.ModelMBeanOperationInfo类的实例,监听器是 javax.management.modelmbean.ModelMBeanNotificationInfo类的实例,

      JMX提供了ModelMBeanInfo接口的默认实现,即javax.management.modelmbean.ModelMBeanInfoSupport类。下面展示一下 我们后面要使用的ModelMBeanInfoSupport类的构造函数:

    public ModelMBeanInfoSupport(String className,
                String description,
                ModelMBeanAttributeInfo[] attributes,
                ModelMBeanConstructorInfo[] constructors,
                ModelMBeanOperationInfo[] operations,
                ModelMBeanNotificationInfo[] notifications) {
            this(className, description, attributes, constructors,
                    operations, notifications, null);
        }

    可以通过调用ModelMBeanAttributeInfo类的构造函数来创建ModelMBeanAttributeInfo对象:

     public ModelMBeanAttributeInfo(String name,
                                           String type,
                                           String description,
                                           boolean isReadable,
                                           boolean isWritable,
                                           boolean isIs,
                                           Descriptor descriptor)

    下面是参数列表:

    • name:属性的名称
    • type,属性的类型名
    • description:对属性的描述
    • isReadable:,true表示针对该属性有一个getter方法,false表示没有
    • isWriteable:true 表示针对该属性有一个 setter方法,false表示没有
    • isIs,true 表示针对该属性有一个getter方法 ,false表示没有
    • descriptor:Descriptor类的实例,包含Attribute的适当元数据,如果它为null,会创建默认的Descriptor实例。

    可以使用下面的构造函数创建一个 ModelMBeanOperationInfo对象

     public ModelMBeanOperationInfo(String name,
                                           String description,
                                           MBeanParameterInfo[] signature,
                                           String type,
                                           int impact,
                                           Descriptor descriptor)

    下面是参数列表;

    • name:方法名
    • description :方法描述
    • signature:MBeanParameterInfo对象的数组,描述了方法的参数
    • type:方法的返回值类型
    • impact:方法的影响 是一个整型变量 ,为了方便大家的使用 使用了javax.management.MBeanOperationInfo类中的几种常量来表示   
    1.     /**
           * 方法返回信息但不改变任何状态
           */
          public static final int INFO = 0;
    2.  /**
           *    指示该操作是写式的:它具有效果,但不从MBean返回任何信息
           */
          public static final int ACTION = 1;
    3.  /**
           *指示该操作既读又写:它具有效果,并且还返回来自MBean的信息
           */
          public static final int ACTION_INFO = 2;
    4.  /**
           * 指示操作的影响是未知的,或者无法使用其他值之一来表示。
           */
          public static final int UNKNOWN = 3;

      只可以选择上面的四种

    • descriptor:Descriptor实例,包含MBeanOperationInfo实例的适当元数据

     我们还是使用原来的Car类作为MBean的管理对象代码如下

    package myex20.pyrmont.Standardmbeantest;
    
    /**
     * <p>
     * <b>Title:Car.java</b>
     * </p>
     * <p>
     * Copyright:ChenDong 2018
     * </p>
     * <p>
     * Company:仅学习时使用
     * </p>
     * <p>
     * 类功能描述:
     * </p>
     * 
     * @author 陈东
     * @date 2018年12月4日 下午7:34:25
     * @version 1.0
     */
    public class Car {
        private String color = "red";
    
        public String getColor() {
            return color;
        }
    
        public void setColor(String color) {
            this.color = color;
        }
    
        public void drive() {
            System.out.println("Baby you can drive my*" + color + "*car.");
        }
    }

    对于模型MBean,不需要像使用标准MBean那样,编写一个接口,只需要实例化RequiredMBean类,下面展示一个ModelAgent类的定义,该类用来创建模型MBean实例,并管理Car对象。

      1 package myex20.pyrmont.modelmbeantest1;
      2 
      3 import javax.management.Attribute;
      4 import javax.management.AttributeNotFoundException;
      5 import javax.management.Descriptor;
      6 import javax.management.InstanceNotFoundException;
      7 import javax.management.InvalidAttributeValueException;
      8 import javax.management.MBeanException;
      9 import javax.management.MBeanInfo;
     10 import javax.management.MBeanOperationInfo;
     11 import javax.management.MBeanParameterInfo;
     12 import javax.management.MBeanServer;
     13 import javax.management.MBeanServerFactory;
     14 import javax.management.MalformedObjectNameException;
     15 import javax.management.ObjectName;
     16 import javax.management.ReflectionException;
     17 import javax.management.RuntimeOperationsException;
     18 import javax.management.modelmbean.DescriptorSupport;
     19 import javax.management.modelmbean.InvalidTargetObjectTypeException;
     20 import javax.management.modelmbean.ModelMBean;
     21 import javax.management.modelmbean.ModelMBeanAttributeInfo;
     22 import javax.management.modelmbean.ModelMBeanInfo;
     23 import javax.management.modelmbean.ModelMBeanInfoSupport;
     24 import javax.management.modelmbean.ModelMBeanOperationInfo;
     25 import javax.management.modelmbean.RequiredModelMBean;
     26 
     27 /**
     28  * <p>
     29  * <b>Title:ModelAgent.java</b>
     30  * </p>
     31  * <p>
     32  * Copyright:ChenDong 2018
     33  * </p>
     34  * <p>
     35  * Company:仅学习时使用
     36  * </p>
     37  * <p>
     38  * 类功能描述:用于创建模型MBean的实例,在该类中用其JMX参考中的默认实现RequiredModelMBean,并管理Car
     39  * 并包含一个MBeanServer实例
     40  * 
     41  * </p>
     42  * <p>
     43  * 请访问下面网址 进行 参考学习 {@see https://www.cnblogs.com/ChenD/p/10061598.html}
     44  * </p>
     45  * 
     46  * @author 陈东
     47  * @date 2018年12月5日 下午9:24:36
     48  * @version 1.0
     49  */
     50 public class ModelAgent {
     51     /**
     52      * 管理的Car类的完全限定名
     53      */
     54     private String MANAGED_CLASS_NAME = "myex20.pyrmont.modelmbeantest1.Car";
     55 
     56     /**
     57      * 用于管理MBean的MBeanServer实例
     58      */
     59     private MBeanServer mBServer = null;
     60 
     61     public ModelAgent() {
     62         mBServer = MBeanServerFactory.createMBeanServer();
     63     }
     64 
     65     public MBeanServer getMBeanServer() {
     66         return mBServer;
     67     }
     68 
     69     /**
     70      * 
     71      * 
     72      * <p>
     73      * Title: createObjectName
     74      * </p>
     75      * 
     76      * @date 2018年12月5日 下午9:39:47
     77      * 
     78      *       <p>
     79      *       功能描述:用指定的name创建ObjectName对象
     80      *       </p>
     81      * 
     82      * @param name
     83      * @return
     84      */
     85     private ObjectName createObjectName(String name) {
     86         ObjectName obj = null;
     87 
     88         try {
     89             obj = new ObjectName(name);
     90         } catch (MalformedObjectNameException e) {
     91 
     92             e.printStackTrace();
     93         }
     94         return obj;
     95 
     96     }
     97 
     98     /**
     99      * 
    100      * 
    101      * <p>
    102      * Title: createMBean
    103      * </p>
    104      * 
    105      * @date 2018年12月6日 下午9:39:09
    106      * 
    107      *       <p>
    108      *       功能描述:创建 ModelMBean
    109      *       </p>
    110      * 
    111      * @param objectName
    112      * @param mbeanName
    113      * @return
    114      */
    115     private ModelMBean createMBean(ObjectName objectName, String mbeanName) {
    116         // ModelMBeanInfo接口描述了要通过ModelMBean暴露给代理层的构造函数、属性、方法、和监听器
    117         // 先创建一个描述 要创建的ModelMBean类 要暴露给代理层的 各种 信息
    118         ModelMBeanInfo mBeanInfo = createModelMBeanInfo(objectName, mbeanName);
    119         RequiredModelMBean modelMBean = null;
    120         try {
    121             modelMBean = new RequiredModelMBean(mBeanInfo);
    122         } catch (Exception e) {
    123             e.printStackTrace();
    124         }
    125         return modelMBean;
    126     }
    127 
    128     /**
    129      * 
    130      * 
    131      * <p>
    132      * Title: createModelMBeanInfo
    133      * </p>
    134      * 
    135      * @date 2018年12月5日 下午10:03:03
    136      * 
    137      *       <p>
    138      *       功能描述:为ModelMBean 类创建类信息 ModelMBeanInfo
    139      * 
    140      *       </p>
    141      *       <p>
    142      *       对象 ModelMBeanInfo对象的几个子接口 构造函数是
    143      *       javax.management.modelmbean.ModelMBeanConstructorInfo类的实例,
    144      *       属性是javax.
    145      *       management.modelmbean.ModelMBeanAttributeInfo类的实例,方法是javax.
    146      *       management.modelmbean.ModelMBeanOperationInfo类的实例,监听器是
    147      *       javax.management.modelmbean.ModelMBeanNotificationInfo类的实例,
    148      *       </p>
    149      * 
    150      * @param inMBeanObjectName
    151      * @param inMBeanName
    152      * @return
    153      */
    154     private ModelMBeanInfo createModelMBeanInfo(ObjectName inMBeanObjectName, String inMBeanName) {
    155 
    156         // ModelMBean类的 类信息接口
    157         ModelMBeanInfo mBeaninfo = null;
    158         // ModelMBean类的 属性 对象集合
    159         ModelMBeanAttributeInfo[] attributes = new ModelMBeanAttributeInfo[1];
    160         // ModelMBean类的 方法 对象集合
    161         ModelMBeanOperationInfo[] operations = new ModelMBeanOperationInfo[3];
    162         try {
    163 
    164             // 属性名:Color,类型:java.lang.String 描述信息:the Color。 isReadable:true
    165             // 有getter方法,isWriteable:true 有setter方法
    166             // isIS :false 无getter方法,descriptor :无
    167             attributes[0] = new ModelMBeanAttributeInfo("Color", "java.lang.String", "the Color.", true, true, false,
    168                     null);
    169             /**
    170              * 第三个参数为 该方法的参数数组 null代表无参数,
    171              */
    172             operations[0] = new ModelMBeanOperationInfo("drive", "the drive method", null, "void",
    173                     MBeanOperationInfo.ACTION, null);
    174             /**
    175              * Car的getColor方法
    176              * 
    177              */
    178             operations[1] = new ModelMBeanOperationInfo("getColor", "get color attribute", null, "java.lang.String",
    179                     MBeanOperationInfo.ACTION, null);
    180 
    181             // setColor方法
    182             String fileds[] = new String[] { "name=setColor", "descriptorType=operation", "class=" + MANAGED_CLASS_NAME,
    183                     "role=operation" };
    184             Descriptor setColorDesc = new DescriptorSupport(fileds);
    185             /**
    186              * MBeanOperationInfo 描述方法的参数对象
    187              */
    188             MBeanParameterInfo[] setColorParams = new MBeanParameterInfo[] {
    189                     new MBeanParameterInfo("new color", "java.lang.String", "new Color value") };
    190             /**
    191              * name:方法名 description :方法描述
    192              * signature:MBeanParameterInfo对象的数组,描述了方法的参数 type:方法的返回值类型
    193              * impact:方法的影响 是一个整型变量 ,为了方便大家的使用
    194              * 使用了javax.management.MBeanOperationInfo类中的几种常量来表示
    195              * ACTION:指示该操作是写式的:它具有效果,但不从MBean返回任何信息
    196              */
    197 
    198             operations[2] = new ModelMBeanOperationInfo("setColor", "set color attribute", setColorParams, "void",
    199                     MBeanOperationInfo.ACTION, setColorDesc);
    200 
    201             mBeaninfo = new ModelMBeanInfoSupport(MANAGED_CLASS_NAME, null, attributes, null, operations, null);
    202 
    203         } catch (Exception e) {
    204             e.printStackTrace();
    205         }
    206         return mBeaninfo;
    207 
    208     }
    209 
    210     public static void main(String[] args) {
    211 
    212         ModelAgent agent = new ModelAgent();
    213         MBeanServer server = agent.getMBeanServer();
    214         Car car = new Car();
    215         // 获取 MBeanServer实例的默认域
    216         String domain = server.getDefaultDomain();
    217         ObjectName objectName = agent.createObjectName((domain + ":type=MyCar"));
    218         String mbeanName = "myMBean";
    219         ModelMBean bean = agent.createMBean(objectName, mbeanName);
    220         // 在创建了ModelMBean对象之后,需要调用ModelMbean接口的setManagedResource方法将
    221         // ModelMBean与其托管的资源相互关联,
    222         // public void setManagedResource(java.lang.Object managedResource,
    223         // java.lang.String managedResourceType) throws MBeanException,
    224         // RuntimeOperationsException, InstanceNotFoundException,
    225         // InvalidTargetObjectTypeException ;
    226         // managedResourceType 目前只支持 ObjectReference
    227         try {
    228             bean.setManagedResource(car, "ObjectReference");
    229             // 将与托管资源关联好的ModelMBean 注册到 MBean服务器中
    230             server.registerMBean(bean, objectName);
    231 
    232         } catch (Exception e) {
    233             // TODO Auto-generated catch block
    234             e.printStackTrace();
    235         }
    236         // 管理代理类
    237 
    238         try {
    239             Attribute attribute = new Attribute("Color", "green");
    240             server.setAttribute(objectName, attribute);
    241             String color = (String) server.getAttribute(objectName, "Color");
    242             System.out.println("Color:" + color);
    243 
    244             attribute = new Attribute("Color", "blue");
    245             server.setAttribute(objectName, attribute);
    246             color = (String) server.getAttribute(objectName, "Color");
    247             System.out.println("Color:" + color);
    248             
    249        251             server.invoke(objectName, "drive", null, null);
    252             server.invoke(objectName, "setColor", new String[]{"blue"},new String[]{"java.lang.String"});
    253             server.invoke(objectName, "drive", null, null);
    254 
    255         } catch (Exception e) {
    256             // TODO Auto-generated catch block
    257             e.printStackTrace();
    258         }
    259 
    260     }
    261 
    262 }

    在执行main之后 的运行结果

    Color:green
    Color:blue
    Baby you can drive my*red*car.
    Baby you can drive my*blue*car.

    因为在使用MBeanServer类的invoke时  看下方法签名吧 我一次传带参数的值 就传错了 记录下

    public Object invoke(ObjectName name, String operationName,
                             Object params[], String signature[])
                throws InstanceNotFoundException, MBeanException,
                       ReflectionException;
    • name: 注册时 用的ObjectName对象
    • operationName:要调用的方法名
    • params:代表参数数组 定义成Object 是为了可以满足任何类型的参数 ,按照参数顺序依次 定义数组内容
    • signature:也是一个数组 代表 参数 元素的 类型 例如 参数是String 那么它的类型 就是 java.lang.String 

    从上面的例子我们已经看出来了 最麻烦的就是创建ModelMBeanInfo信息了,如果这个步骤不可以简化 那么这个ModelMBean将不具备可用性,

    那么为了简化创建ModelMBeanInfo信息引入了一个Commons Modeler 库

    Commons Modeler

       Commons Modeler 库是Apache软件基金会的Jakarta项目的一部分,目的就是使编写模型MBean更加方便,事实上最大的帮助是不需要向上面一样写创建ModelMBeanInfo对象的代码了。

    回忆下之前的例子,在创建RequiredModelMBean实例时,需要创建一个ModelMBeanInfo对象,并将其传给RequiredModelMBean类的构造函数:

    ModelMBeanInfo mBeanInfo = createModelMBeanInfo(objectName, mbeanName);
            RequiredModelMBean modelMBean = null;
            try {
                modelMBean = new RequiredModelMBean(mBeanInfo);
            } catch (Exception e) {
                e.printStackTrace();
            }

    ModelMbeanInfo对象描述了将要由MBean实例暴露出来的属性和方法,实现createModelMBeanInfo方法是特别枯燥的而且麻烦死了,因为必须列出所有要暴露出来的属性和方法 并将它们传给ModelMBeanInfo对象。

      而使用Commons Modeler库,就不在需要创建ModelMBeanInfo对象了,相反对模型MBean的描述被封装在一个 org.apache.catalina.modeler.ManagedBean对象中。不需要编写代码在MBean中暴露出属性和方法。只需要编写一个mbean描述文件(一个XML文档),列出想要创建的MBean,对于每个MBean,需要写出MBean类和托管资源类的完全限定名,此外还有由MBean暴露出来的属性和方法,然后使用org.apache.commons.modeler.Registry实例来读取这个XML文档,并创建一个MBeanServer实例,在按照mbean描述文件中的XML元素创建所有的ManagedBean实例。

      然后调用ManagedBean实例的createMBean方法创建模型MBean,这之后就是普通的流程了,需要创建ObjectName对象的实例,并将其与MBean实例一起注册到MBean服务器中,下面会先介绍一下mbean描述文件的格式,然后讨论Modeler库中的三个重要的类,分别是Registry类,ManagedBean类、和BaseModelMBean类。

    注意:为了更好的理解Modeler库,org.apache.catalina.mbeans包中与MBean相关类的工作原理 。我们仍然使用老版本,

     MBean描述符

      MBean描述符是一个XML 文档,该文档描述了将会由Mbean服务器管理的 ModelMBean的实例,MBean描述符以下面的头信息开始:

    <?xml version="1.0"?>
    <!DOCTYPE mbeans-descriptors PUBLIC
    "-//Apache Software Foundation//DTD Model MBeans Configuration File"
    "http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd">

      接下来是mbeans-descriptors的根元素

    <mbeans-descriptors>
    ...
    </mbeans-descriptors>

      在开始和末尾的mbeans-descriptors标签内部是mbean元素,每一个mbean元素标签表示一个模型MBean,mbean元素包含了分别用来表示属性、方法、构造函数、和通知的元素。

    mbean元素

      mbean元素描述了一个模型MBean,包含创建对应ModelMBeanInfo对象的信息。mbean元素的定义如下所示:

    <!ELEMENT mbean(descriptor?,attribute*,constructor*,notification*,operation*)>

      mbean元素定义了具体的规范,mbean元素可以有一个可选的descriptor元素,0个或者多个attribute元素。0个或者多个constructor元素,0个或者多个notification元素。0个或者多个operation元素。

      mbean元素可以有如下的属性:

    • className :实现ModelMBean接口的java类的完全限定名,若该属性未赋值,则默认使用org.apache.commons.modeler.BaseModelMBean类;
    • description: 该ModelMBean类的简单描述
    • domain:在创建ModelMBean的ObjectName对象时,托管的bean 的 ModelMBean实例被注册到MBeanServer的域名。
    • group: 组分类的可选名,可以用来选择具有相似MBean实例类的组;
    • name:唯一标识模型MBean的名称,一般情况下,会使用相关服务器组件的基类名。
    • type:托管资源实现类的完全限定java类名。
    attribute 元素

      使用attribute元素描述MBean的javaBean属性。attribute元素有一个可选的descripotr元素,attribute元素可以由如下的属性:

    • description:该属性的简单描述
    • displayName:该属性的显示名称;
    • getMethod:返回 attribute元素 的getter方法;
    • is:一个布尔值,指明该属性是否是一个布尔值,是否有getter方法,默认情况下,该属性值为false;
    • name:该javaBean属性的名称:
    • readable:一个布尔值,指明该属性对管理应用程序来说是否可读,该属性默认值为 true;
    • setMethod,设置 attribute属性的setter方法;
    • type:该属性的完全限定java类名;
    • writeable:一个布尔值。指明该属性对管理应用程序来说是否可写,该属性的默认值为true;
    operation 元素

      operation元素描述了模型MBean 中要暴露给管理应用程序的公共方法,它可以有.个或者多个parameter子元素和如下的属性:

    • description:方法的简单描述
    • impact:指明方法的影响,可选值,ACTION、ACTION-INFO、INFO或UNKNOWN;值的意思参考  ModelMBeanOperationInfo对象 的讲述;
    • name:公共方法的名称;
    • returnType:方法返回值的完全限定的java类名。
    parameter 元素

      parameter元素描述了将要传递给构造函数 或者 方法的参数,它可以有如下的属性:

    • description:该参数的简单描述
    • name:参数名
    • type:该参数完全限定的java类名

    mbean元素的示例

      在Catalin的 mbean-descriptors.xml文件中声明了一系列模型MBean,该文件位于org.apache.catalina.mbean 包下,下面给出了 mbean-descriptors.xml文件中对于StandardServer MBean的声明

    <mbean name="StandardServer" className="org.apache.catalina.mbeans.StandardServerMBean"
    description="Standard Server Component"
    domain="Catalina"
    group="Server"
    type="org.apache.catalina.core.StandardServer">
    
    <attribute name="debug"
    description="The debugging detail level fot this component"
    type="int"/>
    
    <attribute name="managedResource"
    description="The managed resource this MBean is asscoiated with"
    type="java.lang.Object"/>
    
    <attribute name="port"
    description="TCP port for shutdown messages"
    type="int"/>
    
    <attribute name="shutdown"
    description="Shutdown password"
    type="java.lang.String"/>
    
    <operation name="store" 
    description="Save current state to server.xml file"
    impact="ACTION"
    returnType="void">
    </operation>
    </mbean>

    上述代码中的mbean元素声明了一个模型MBean,其唯一标识是StandardServer,该MBean是org.apache.catalina.mbeans.StandardServerMBean类的一个对象,负责管理org.apache.catalina.core.StandardServer类的对象。

    domain属性的值是 Catalina,group的属性是Server。

      模型MBean暴露出的属性有四个,分别是debug、managedResource、port和shutdown。正如mbean元素中嵌套的四个attribute元素所描述的一样,此外,Mbean还暴露出了一个方法,即 store方法,由 operation元素描述。

    自己编写一个模型MBean类

     使用Commons Modeler库,需要在mbean元素的className属性中指明自定义的模型MBean的类型,默认情况下,Commons Modeler库使用 org.apache.commons.modeler.BaseModelMBean类。

    有以下两种情况。其中可能需要对BaseModelMBean类进行扩展:

    • 需要覆盖托管资源的属性或方法
    • 需要添加在托管资源中没有定义的属性或方法

    在org.apahce.catalina.mbeans包下,Catalina 提供了BaseModelMBean类的很多子类,可以用来实现上面的需求。

    Registry类.

    org.apahce.commons.modeler.Registry类定义了很多方法,下面是可以使用该类做的事情。

    • 获取 javax.managedment.MBeanServer类的一个实例,所以不需要在调用javax.managedment.MbeanServerFactory类的createMBeanServer方法了
    • 使用 loadRegistry方法获取MBean的描述文件
    • 创建一个ManagedBean对象,用于创建模型MBean的实例。

    ManagedMBean

      ManagedMBean对象描述了一个模型MBean,该类用于取代javax.managedment.MBeanInfo对象。

    BaseModelMBean

      org.apache.commons.modeler.BaseModelMbean类实现了 javax.managedment.modelmbean.ModelMBean接口,使用这个类,就不需要使用javax.managedment.modelmbean.RequiredMoldeMBean这个类了,

      该类用一个比较有用的字段是resource字段。resource字段表示该模型MBean管理的资源。resource字段的定义如下;

    protected  java.lang.Object resource = null;

    使用Modeler库 API

    下面代码给出了想要管理器对象Car类的定义

     1 package myex20.pyrmont.modelmbeantest2;
     2 
     3 /**
     4  * <p>
     5  * <b>Title:Car.java</b>
     6  * </p>
     7  * <p>
     8  * Copyright:ChenDong 2018
     9  * </p>
    10  * <p>
    11  * Company:仅学习时使用
    12  * </p>
    13  * <p>
    14  * 类功能描述:modelmbeantest2 中 要被管理的对象
    15  * </p>
    16  * 
    17  * @author 陈东
    18  * @date 2018年12月10日 下午10:20:53
    19  * @version 1.0
    20  */
    21 public class Car {
    22     public Car() {
    23         System.out.println("Car constructor");
    24     }
    25 
    26     private String color = "red";
    27 
    28     public String getColor() {
    29 
    30         return this.color;
    31     }
    32 
    33     public void setColor(String color) {
    34         this.color = color;
    35     }
    36 
    37     public void drive() {
    38         System.out.println("Baby  you can drive my " + color + " Car");
    39     }
    40 
    41 }

      使用Commons Modeler 库,不需要使用硬编码的方式,将托管对象的所有属性和方法都写在代码中,相反,可以将他们写在一个xml文件中,作为MBean的描述符文件,在这个例子当中,这样的文档是car-mbean-descriptor.xml文件,如下面所所示

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mbeans-descriptors PUBLIC
     "-//Apache Software Foundation//DTD Model MBeans Configuration File"
     "http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd">
     
    <mbeans-descriptors>
    
      <mbean name="myMBean"
        className="javax.management.modelmbean.RequiredModelMBean"
        description="The ModelMBean that manages our Car object"
        type="ex20.pyrmont.modelmbeantest.Car">
    
        <attribute name="Color"
          description="The car color"
          type="java.lang.String"/>
    
        <operation name="drive"
          description="drive method"
          impact="ACTION"
          returnType="void">
          <parameter name="driver" description="the driver parameter"
            type="java.lang.String"/>
        </operation>
    
      </mbean>
    
    </mbeans-descriptors>

    那么我们写完这个描述文件之后,就需要一个在写一个代理类ModelAgent.java,具体看下面哈

    package myex20.pyrmont.modelmbeantest2;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.URL;
    
    import javax.management.Attribute;
    import javax.management.MBeanServer;
    import javax.management.MalformedObjectNameException;
    import javax.management.ObjectName;
    import javax.management.modelmbean.ModelMBean;
    
    import org.apache.commons.modeler.ManagedBean;
    import org.apache.commons.modeler.Registry;
    
    /**
     * <p>
     * <b>Title:ModelAgent.java</b>
     * </p>
     * <p>
     * Copyright:ChenDong 2018
     * </p>
     * <p>
     * Company:仅学习时使用
     * </p>
     * <p>
     * 类功能描述: modelmbeantest2包下的代理类
     * </p>
     * 
     * @author 陈东
     * @date 2018年12月11日 下午7:43:28
     * @version 1.0
     */
    public class ModelAgent {
        /**
         * <p>
         * 作用1:获取 {@link javax.management.MBeanServer }
         * </p>
         * 
         * <p>
         * 作用2:使用loadRegistry方法来读取mbean描述文件;
         * </p>
         * 
         * <p>
         * 作用3:创建一个@
         * {@link org.apache.commons.modeler.ManagedBean}用于创建一个{@code ModelMBean}
         * </p>
         */
        private Registry registry;
    
        private MBeanServer mbeanServer;
    
        public ModelAgent() {
            registry = createRegistry();
            mbeanServer = Registry.getServer();
        }
    
        public MBeanServer getMBeanServer() {
            return mbeanServer;
        }
    
        /**
         * 
         * 
         * <p>
         * Title: createRegistrt
         * </p>
         * 
         * @date 2018年12月11日 下午8:28:44
         * 
         *       <p>
         *       功能描述:创建Registry,
         *       </p>
         * 
         * @return
         */
        private Registry createRegistry() {
    
            Registry registry = null;
    
            try {
                URL url = ModelAgent.class.getResource("/myex20/pyrmont/modelmbeantest2/car-mbean-descriptor.xml");
                InputStream io = url.openStream();
                Registry.loadRegistry(io);
                registry = Registry.getRegistry();
            } catch (Exception e) {
    
                e.printStackTrace();
            }
            return registry;
        }
    
        /**
         * 
         * 
         * <p>
         * Title: createModleMBean
         * </p>
         * <p>
         * 功能描述:用于创建指定名字的 ModelMBean 这里的名字必须是 mbean描述文件中的 mbean 元素的name属性所指定的才可以
         * 否则返回null
         * </p>
         * 
         * @date 2018年12月11日 下午8:46:54
         * 
         * 
         * 
         * @param mbeanName
         * @return
         * @throws Exception
         */
        private ModelMBean createModleMBean(String mbeanName) throws Exception {
            // 根据指定的名字去找mbean描述文件中对应的配置所代表的 ManagedBean对象
            ManagedBean managed = registry.findManagedBean(mbeanName);
            if (managed == null) {
                System.out.println("ManagedBean is null");
                return null;
            }
            // 创建ModelMBean
            ModelMBean mbean = managed.createMBean();
    
            return mbean;
        }
    
        /**
         * 
         * 
         * <p>
         * Title: createObjectName
         * </p>
         * 
         * @date 2018年12月11日 下午8:45:25
         * 
         *       <p>
         *       功能描述:创建用于向mbean服务器注册时为MBean做唯一标识 的ObjectName
         *       </p>
         * 
         * @return
         */
        private ObjectName createObjectName() {
            ObjectName objectname = null;
            String domain = mbeanServer.getDefaultDomain();
            try {
                objectname = new ObjectName(domain + ":type=MyCar");
            } catch (MalformedObjectNameException e) {
    
                e.printStackTrace();
            }
    
            return objectname;
        }
    
        public static void main(String[] args) {
            // 实例化代理类
            ModelAgent agent = new ModelAgent();
            // 使用代理类 获取MBeanServer
            MBeanServer server = agent.getMBeanServer();
            // 要被托管的资源
            Car car = new Car();
            // 创建ObjectName
            ObjectName objectName = agent.createObjectName();
    
            try {
                // 创建ModelMBean对象 名字必须在mbean 描述文件中有对应mbean元素
                ModelMBean modelMBean = agent.createModleMBean("myMBean");
                // 将托管资源 与 modelMBean对象关联起来
                /**
                 * 在创建了ModelMBean对象之后,需要调用ModelMbean接口的setManagedResource方法将
                 * ModelMBean与其托管的资源相互关联, public void
                 * setManagedResource(java.lang.Object managedResource,
                 * java.lang.String managedResourceType) throws MBeanException,
                 * RuntimeOperationsException, InstanceNotFoundException,
                 * InvalidTargetObjectTypeException ; managedResourceType 目前只支持
                 * ObjectReference
                 */
                modelMBean.setManagedResource(car, "ObjectReference");
                // 将modelMBean 注册到 mbeanServer
                server.registerMBean(modelMBean, objectName);
    
            } catch (Exception e) {
    
                e.printStackTrace();
            }
    
            // 管理这个托管资源
            try {
    
                Attribute attribute = new Attribute("Color", "green");
                server.setAttribute(objectName, attribute);
                String color = (String) server.getAttribute(objectName, "Color");
                System.out.println("mbeanserver getAttribute  Color:" + color);
                System.out.println("Car's Color:" + car.getColor());
    
                attribute = new Attribute("Color", "blue");
                server.setAttribute(objectName, attribute);
                color = (String) server.getAttribute(objectName, "Color");
                System.out.println("mbeanserver getAttribute  Color:" + color);
                System.out.println("Car's Color:" + car.getColor());
    
                server.invoke(objectName, "drive", null, null);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
    }

    运行main方法后的结果

    十二月 11, 2018 9:41:28 下午 org.apache.commons.modeler.Registry loadRegistry
    信息: Loading registry information
    十二月 11, 2018 9:41:28 下午 org.apache.commons.modeler.Registry getRegistry
    信息: Creating new Registry instance
    十二月 11, 2018 9:41:28 下午 org.apache.commons.modeler.Registry getServer
    信息: Creating MBeanServer
    十二月 11, 2018 9:41:28 下午 org.apache.commons.modeler.Registry loadRegistry
    信息: Loading registry information
    Car constructor
    mbeanserver getAttribute  Color:green
    Car's Color:green
    mbeanserver getAttribute  Color:blue
    Car's Color:blue
    Baby  you can drive my blue Car

    看下我们在使用了Commons Modeler库之后 减少了好多代码吧

    Catalina中的MBean

      Catalina 在 org.apache.catalina.mbeans包中提供了一系列的MBean类,这些MBean类都直接 或者间接的继承自 org.apahce.commons.modeler.BaseModelMBean类,下面会为大家展示一下 Tomcat 4 中  三个最重要的MBean类,分别是ClassNameMBean类,

    StandardServerMBean类、和MBeanFactory类,还有一个重要的工具类 MBeanUtil类。

    BaseModelMBean类

      因为下面要讲解的类直接或者间接都会继承该类,所以有必要讲解下 该类的一些 重要的属性 以及方法

    首先 有一个 java.lang.Object 类型名为 resource的变量 表示 托管资源的实例对象

    protected Object resource = null;

    还有一个重要的方法也就 将托管资源 和 该ModelMBean相关联的方法 setManagedResource(Object resource,String type),看下面的展示

        /**
         * 
         * 
         * <p>
         * Title: setManagedResource
         * </p>
         * 
         * @date 2018年12月11日 下午10:13:06
         * 
         *       <p>
         *       功能描述: 将 指定的 托管资源 resource ,绑定到当前的ModelMBean中
         *       </p>
         * 
         * @param resource 指定的托管资源
         * @param type 指定type 目前只支持 {@code objectreference} 
         * @throws InstanceNotFoundException
         * @throws InvalidTargetObjectTypeException 若 type 不为 {@code objectreference} 抛出错误
         * @throws MBeanException
         * @throws RuntimeOperationsException 若 指定的托管资源resource是null 则抛出错误
         */
        public void setManagedResource(Object resource, String type) throws InstanceNotFoundException,
                InvalidTargetObjectTypeException, MBeanException, RuntimeOperationsException {
            if (resource == null) {
                throw new RuntimeOperationsException(new IllegalArgumentException("Managed resource is null"),
                        "Managed resource is null");
            } else if (!"objectreference".equalsIgnoreCase(type)) {
                throw new InvalidTargetObjectTypeException(type);
            } else {
                this.resource = resource;
            }
        }

    ClassNameMBean

      org.apahce.catalina.mbeans.ClassNameMBean类 继承自 org.apache.commons.modeler.BaseModelMBean类,它提供了一个属性className,用于表示托管资源的类名,详细的内容看下面

     1 package org.apache.catalina.mbeans;
     2 
     3 import javax.management.MBeanException;
     4 import javax.management.RuntimeOperationsException;
     5 import org.apache.commons.modeler.BaseModelMBean;
     6 
     7 /**
     8  * 
     9  * <p>
    10  * <b>Title:ClassNameMBean.java</b>
    11  * </p>
    12  * <p>
    13  * Copyright:ChenDong 2018
    14  * </p>
    15  * <p>
    16  * Company:仅学习时使用
    17  * </p>
    18  * <p>
    19  * 类功能描述:这个类创建一个名为className属性,该属性将托管对象的完全限定类名报告为其值。
    20  * </p>
    21  * 
    22  * @author 陈东
    23  * @date 2018年12月11日 下午10:18:52
    24  * @version 1.0
    25  */
    26 public class ClassNameMBean extends BaseModelMBean {
    27 
    28     // ---------------------------------------------------------- Constructors
    29 
    30     /**
    31      * 
    32      * 用默认的<code>ModelMBeanInfo</code>信息构造ModelMBean。
    33      * 
    34      * @exception MBeanException
    35      *                如果对象的初始化引发异常
    36      * @exception RuntimeOperationsException
    37      *                如果发生错误
    38      */
    39     public ClassNameMBean() throws MBeanException, RuntimeOperationsException {
    40 
    41         super();
    42 
    43     }
    44 
    45     // ------------------------------------------------------------ Properties
    46 
    47     /**
    48      * 返回其托管资源类的完全限定名
    49      */
    50     public String getClassName() {
    51 
    52         return (this.resource.getClass().getName());
    53 
    54     }
    55 
    56 }

      ClassNameMBean类时BaseModelMBean类的子类,其属性className在托管资源中是不可见的,mbeans-descriptors.xml文件中的很多mbean元素使用该类作为其ModelMBean的类型。

    StandardServerMBean类

      StandardServerMBean类继承自 org.apache.commons.modeler.BaseModelMBean类,用于管理 org.apache.catalina.core.StandardServer类的实例,StandardServerMBean类是ModelMBean类的一个示例,它重写了托管资源的store方法,当管理应用程序调用store方法的时候,实际上会执行StandardServerMBean实例的store方法,而不是托管资源StandardServer对象的store方法,

     1 package org.apache.catalina.mbeans;
     2 
     3 
     4 import javax.management.InstanceNotFoundException;
     5 import javax.management.MBeanException;
     6 import javax.management.MBeanServer;
     7 import javax.management.RuntimeOperationsException;
     8 import org.apache.catalina.Server;
     9 import org.apache.catalina.ServerFactory;
    10 import org.apache.catalina.core.StandardServer;
    11 import org.apache.commons.modeler.BaseModelMBean;
    12 
    13 
    14 /**
    15  * 
    16  * <p>
    17  * <b>Title:StandardServerMBean.java</b>
    18  * </p>
    19  * <p>
    20  * Copyright:ChenDong 2018
    21  * </p>
    22  * <p>
    23  * Company:仅学习时使用
    24  * </p>
    25  * <p>
    26  * 类功能描述: {@code org.apache.catalina.core.StandardServer} 组件的ModelMBean实现。
    27  * </p>
    28  * 
    29  * @author 陈东
    30  * @date 2018年12月13日 下午7:36:09
    31  * @version 1.0
    32  */
    33 
    34 public class StandardServerMBean extends BaseModelMBean {
    35 
    36 
    37     // ------------------------------------------------------- Static Variables
    38 
    39 
    40     /**
    41      * 应用程序的<code>MBeanServer</code> 组件
    42      */
    43     private static MBeanServer mserver = MBeanUtils.createServer();
    44 
    45 
    46     // ----------------------------------------------------------- Constructors
    47 
    48 
    49     /**
    50      *
    51      * 使用默认的<code>ModelMBeanInfo</code> 实现一个<code>ModelMBean</code>
    52      * 
    53      * @exception MBeanException
    54      *                如果对象的初始化器引发异常
    55      * @exception RuntimeOperationsException
    56      *                
    57      */
    58     public StandardServerMBean() throws MBeanException, RuntimeOperationsException {
    59 
    60         super();
    61 
    62     }
    63 
    64 
    65     // ------------------------------------------------------------- Attributes
    66 
    67 
    68     // ------------------------------------------------------------- Operations
    69 
    70 
    71     /**
    72      * 
    73      * 将整个<code>Server</code>的配置信息写入{@code server.xml}配置文件。
    74      * 
    75      * @exception InstanceNotFoundException
    76      *                如果找不到托管资源对象
    77      * @exception MBeanException
    78      *                如果对象的初始化器抛出异常,或者不支持持久性
    79      * @exception RuntimeOperationsException
    80      *                如果持久性机制报告了异常
    81      */
    82     public synchronized void store() throws InstanceNotFoundException,
    83         MBeanException, RuntimeOperationsException {
    84 
    85         Server server = ServerFactory.getServer();
    86         if (server instanceof StandardServer) {
    87             try {
    88                 ((StandardServer) server).store();
    89             } catch (Exception e) {
    90                 throw new MBeanException(e, "Error updating conf/server.xml");
    91             }
    92         }
    93 
    94     }
    95 
    96 
    97 }
    StandardServerMBean 是一种模型MBean,继承自BaseModelMBean,并重写了托管资源(org.apache.catalina.core.StandardServer)的一个方法
  • 相关阅读:
    理论+实践解析“IT治理”之模式与原则
    iOS开发如何避免安全隐患
    DBA职业发展之路:去“IOE”等挑战之下,DBA将何去何从?
    自动化测试最佳实践(一):从纺锤模型到金字塔模型
    宜信开源|手把手教你安装第一个LAIN应用
    宜信开源|数据库审核软件Themis的规则解析与部署攻略
    开源|性能优化利器:数据库审核平台Themis的选型与实践
    小老板,我300M的网,网速很慢怎么办?
    JSP、ASP、PHP Web应用程序怎么这么多P!
    难道你现在还不知道:C/S和B/S
  • 原文地址:https://www.cnblogs.com/ChenD/p/10061598.html
Copyright © 2020-2023  润新知