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方法的签名;

  1. ObjectInstance registerMBean(java.lang.Object object, ObjectName var2)
  2. 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方法的签名:

  1. 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方法的签名如下:

  1. 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)是一个非空字符串,并且不能包含下列字符:等号、逗号、分号、星号、和问号。在一个对象名称中,同一个键只能出现一次,

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

  1. 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与其托管的资源相互关联,该方法的签名如下

  1. 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类的构造函数:

  1. public ModelMBeanInfoSupport(String className,
  2. String description,
  3. ModelMBeanAttributeInfo[] attributes,
  4. ModelMBeanConstructorInfo[] constructors,
  5. ModelMBeanOperationInfo[] operations,
  6. ModelMBeanNotificationInfo[] notifications) {
  7. this(className, description, attributes, constructors,
  8. operations, notifications, null);
  9. }

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

  1. public ModelMBeanAttributeInfo(String name,
  2. String type,
  3. String description,
  4. boolean isReadable,
  5. boolean isWritable,
  6. boolean isIs,
  7. Descriptor descriptor)

下面是参数列表:

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

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

  1. public ModelMBeanOperationInfo(String name,
  2. String description,
  3. MBeanParameterInfo[] signature,
  4. String type,
  5. int impact,
  6. Descriptor descriptor)

下面是参数列表;

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

    只可以选择上面的四种

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

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

  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 {
  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. }

对于模型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. server.invoke(objectName, "drive", null, null);
  250. server.invoke(objectName, "setColor", new String[]{"blue"},new String[]{"java.lang.String"});
  251. server.invoke(objectName, "drive", null, null);
  252.  
  253. } catch (Exception e) {
  254. // TODO Auto-generated catch block
  255. e.printStackTrace();
  256. }
  257.  
  258. }
  259.  
  260. }

在执行main之后 的运行结果

  1. Color:green
  2. Color:blue
  3. Baby you can drive my*red*car.
  4. Baby you can drive my*blue*car.

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

  1. public Object invoke(ObjectName name, String operationName,
  2. Object params[], String signature[])
  3. throws InstanceNotFoundException, MBeanException,
  4. 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类的构造函数:

  1. ModelMBeanInfo mBeanInfo = createModelMBeanInfo(objectName, mbeanName);
  2. RequiredModelMBean modelMBean = null;
  3. try {
  4. modelMBean = new RequiredModelMBean(mBeanInfo);
  5. } catch (Exception e) {
  6. e.printStackTrace();
  7. }

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描述符以下面的头信息开始:

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

  接下来是mbeans-descriptors的根元素

  1. <mbeans-descriptors>
  2. ...
  3. </mbeans-descriptors>

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

mbean元素

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

  1. <!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的声明

  1. <mbean name="StandardServer" className="org.apache.catalina.mbeans.StandardServerMBean"
  2. description="Standard Server Component"
  3. domain="Catalina"
  4. group="Server"
  5. type="org.apache.catalina.core.StandardServer">
  6.  
  7. <attribute name="debug"
  8. description="The debugging detail level fot this component"
  9. type="int"/>
  10.  
  11. <attribute name="managedResource"
  12. description="The managed resource this MBean is asscoiated with"
  13. type="java.lang.Object"/>
  14.  
  15. <attribute name="port"
  16. description="TCP port for shutdown messages"
  17. type="int"/>
  18.  
  19. <attribute name="shutdown"
  20. description="Shutdown password"
  21. type="java.lang.String"/>
  22.  
  23. <operation name="store"
  24. description="Save current state to server.xml file"
  25. impact="ACTION"
  26. returnType="void">
  27. </operation>
  28. </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字段的定义如下;

  1. 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文件,如下面所所示

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mbeans-descriptors PUBLIC
  3. "-//Apache Software Foundation//DTD Model MBeans Configuration File"
  4. "http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd">
  5.  
  6. <mbeans-descriptors>
  7.  
  8. <mbean name="myMBean"
  9. className="javax.management.modelmbean.RequiredModelMBean"
  10. description="The ModelMBean that manages our Car object"
  11. type="ex20.pyrmont.modelmbeantest.Car">
  12.  
  13. <attribute name="Color"
  14. description="The car color"
  15. type="java.lang.String"/>
  16.  
  17. <operation name="drive"
  18. description="drive method"
  19. impact="ACTION"
  20. returnType="void">
  21. <parameter name="driver" description="the driver parameter"
  22. type="java.lang.String"/>
  23. </operation>
  24.  
  25. </mbean>
  26.  
  27. </mbeans-descriptors>

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

  1. package myex20.pyrmont.modelmbeantest2;
  2.  
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.net.URL;
  6.  
  7. import javax.management.Attribute;
  8. import javax.management.MBeanServer;
  9. import javax.management.MalformedObjectNameException;
  10. import javax.management.ObjectName;
  11. import javax.management.modelmbean.ModelMBean;
  12.  
  13. import org.apache.commons.modeler.ManagedBean;
  14. import org.apache.commons.modeler.Registry;
  15.  
  16. /**
  17. * <p>
  18. * <b>Title:ModelAgent.java</b>
  19. * </p>
  20. * <p>
  21. * Copyright:ChenDong 2018
  22. * </p>
  23. * <p>
  24. * Company:仅学习时使用
  25. * </p>
  26. * <p>
  27. * 类功能描述: modelmbeantest2包下的代理类
  28. * </p>
  29. *
  30. * @author 陈东
  31. * @date 2018年12月11日 下午7:43:28
  32. * @version 1.0
  33. */
  34. public class ModelAgent {
  35. /**
  36. * <p>
  37. * 作用1:获取 {@link javax.management.MBeanServer }
  38. * </p>
  39. *
  40. * <p>
  41. * 作用2:使用loadRegistry方法来读取mbean描述文件;
  42. * </p>
  43. *
  44. * <p>
  45. * 作用3:创建一个@
  46. * {@link org.apache.commons.modeler.ManagedBean}用于创建一个{@code ModelMBean}
  47. * </p>
  48. */
  49. private Registry registry;
  50.  
  51. private MBeanServer mbeanServer;
  52.  
  53. public ModelAgent() {
  54. registry = createRegistry();
  55. mbeanServer = Registry.getServer();
  56. }
  57.  
  58. public MBeanServer getMBeanServer() {
  59. return mbeanServer;
  60. }
  61.  
  62. /**
  63. *
  64. *
  65. * <p>
  66. * Title: createRegistrt
  67. * </p>
  68. *
  69. * @date 2018年12月11日 下午8:28:44
  70. *
  71. * <p>
  72. * 功能描述:创建Registry,
  73. * </p>
  74. *
  75. * @return
  76. */
  77. private Registry createRegistry() {
  78.  
  79. Registry registry = null;
  80.  
  81. try {
  82. URL url = ModelAgent.class.getResource("/myex20/pyrmont/modelmbeantest2/car-mbean-descriptor.xml");
  83. InputStream io = url.openStream();
  84. Registry.loadRegistry(io);
  85. registry = Registry.getRegistry();
  86. } catch (Exception e) {
  87.  
  88. e.printStackTrace();
  89. }
  90. return registry;
  91. }
  92.  
  93. /**
  94. *
  95. *
  96. * <p>
  97. * Title: createModleMBean
  98. * </p>
  99. * <p>
  100. * 功能描述:用于创建指定名字的 ModelMBean 这里的名字必须是 mbean描述文件中的 mbean 元素的name属性所指定的才可以
  101. * 否则返回null
  102. * </p>
  103. *
  104. * @date 2018年12月11日 下午8:46:54
  105. *
  106. *
  107. *
  108. * @param mbeanName
  109. * @return
  110. * @throws Exception
  111. */
  112. private ModelMBean createModleMBean(String mbeanName) throws Exception {
  113. // 根据指定的名字去找mbean描述文件中对应的配置所代表的 ManagedBean对象
  114. ManagedBean managed = registry.findManagedBean(mbeanName);
  115. if (managed == null) {
  116. System.out.println("ManagedBean is null");
  117. return null;
  118. }
  119. // 创建ModelMBean
  120. ModelMBean mbean = managed.createMBean();
  121.  
  122. return mbean;
  123. }
  124.  
  125. /**
  126. *
  127. *
  128. * <p>
  129. * Title: createObjectName
  130. * </p>
  131. *
  132. * @date 2018年12月11日 下午8:45:25
  133. *
  134. * <p>
  135. * 功能描述:创建用于向mbean服务器注册时为MBean做唯一标识 的ObjectName
  136. * </p>
  137. *
  138. * @return
  139. */
  140. private ObjectName createObjectName() {
  141. ObjectName objectname = null;
  142. String domain = mbeanServer.getDefaultDomain();
  143. try {
  144. objectname = new ObjectName(domain + ":type=MyCar");
  145. } catch (MalformedObjectNameException e) {
  146.  
  147. e.printStackTrace();
  148. }
  149.  
  150. return objectname;
  151. }
  152.  
  153. public static void main(String[] args) {
  154. // 实例化代理类
  155. ModelAgent agent = new ModelAgent();
  156. // 使用代理类 获取MBeanServer
  157. MBeanServer server = agent.getMBeanServer();
  158. // 要被托管的资源
  159. Car car = new Car();
  160. // 创建ObjectName
  161. ObjectName objectName = agent.createObjectName();
  162.  
  163. try {
  164. // 创建ModelMBean对象 名字必须在mbean 描述文件中有对应mbean元素
  165. ModelMBean modelMBean = agent.createModleMBean("myMBean");
  166. // 将托管资源 与 modelMBean对象关联起来
  167. /**
  168. * 在创建了ModelMBean对象之后,需要调用ModelMbean接口的setManagedResource方法将
  169. * ModelMBean与其托管的资源相互关联, public void
  170. * setManagedResource(java.lang.Object managedResource,
  171. * java.lang.String managedResourceType) throws MBeanException,
  172. * RuntimeOperationsException, InstanceNotFoundException,
  173. * InvalidTargetObjectTypeException ; managedResourceType 目前只支持
  174. * ObjectReference
  175. */
  176. modelMBean.setManagedResource(car, "ObjectReference");
  177. // 将modelMBean 注册到 mbeanServer
  178. server.registerMBean(modelMBean, objectName);
  179.  
  180. } catch (Exception e) {
  181.  
  182. e.printStackTrace();
  183. }
  184.  
  185. // 管理这个托管资源
  186. try {
  187.  
  188. Attribute attribute = new Attribute("Color", "green");
  189. server.setAttribute(objectName, attribute);
  190. String color = (String) server.getAttribute(objectName, "Color");
  191. System.out.println("mbeanserver getAttribute Color:" + color);
  192. System.out.println("Car's Color:" + car.getColor());
  193.  
  194. attribute = new Attribute("Color", "blue");
  195. server.setAttribute(objectName, attribute);
  196. color = (String) server.getAttribute(objectName, "Color");
  197. System.out.println("mbeanserver getAttribute Color:" + color);
  198. System.out.println("Car's Color:" + car.getColor());
  199.  
  200. server.invoke(objectName, "drive", null, null);
  201. } catch (Exception e) {
  202. e.printStackTrace();
  203. }
  204.  
  205. }
  206.  
  207. }

运行main方法后的结果

  1. 十二月 11, 2018 9:41:28 下午 org.apache.commons.modeler.Registry loadRegistry
  2. 信息: Loading registry information
  3. 十二月 11, 2018 9:41:28 下午 org.apache.commons.modeler.Registry getRegistry
  4. 信息: Creating new Registry instance
  5. 十二月 11, 2018 9:41:28 下午 org.apache.commons.modeler.Registry getServer
  6. 信息: Creating MBeanServer
  7. 十二月 11, 2018 9:41:28 下午 org.apache.commons.modeler.Registry loadRegistry
  8. 信息: Loading registry information
  9. Car constructor
  10. mbeanserver getAttribute Color:green
  11. Car's Color:green
  12. mbeanserver getAttribute Color:blue
  13. Car's Color:blue
  14. 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的变量 表示 托管资源的实例对象

  1. protected Object resource = null;

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

  1. /**
  2. *
  3. *
  4. * <p>
  5. * Title: setManagedResource
  6. * </p>
  7. *
  8. * @date 2018年12月11日 下午10:13:06
  9. *
  10. * <p>
  11. * 功能描述: 将 指定的 托管资源 resource ,绑定到当前的ModelMBean中
  12. * </p>
  13. *
  14. * @param resource 指定的托管资源
  15. * @param type 指定type 目前只支持 {@code objectreference}
  16. * @throws InstanceNotFoundException
  17. * @throws InvalidTargetObjectTypeException 若 type 不为 {@code objectreference} 抛出错误
  18. * @throws MBeanException
  19. * @throws RuntimeOperationsException 若 指定的托管资源resource是null 则抛出错误
  20. */
  21. public void setManagedResource(Object resource, String type) throws InstanceNotFoundException,
  22. InvalidTargetObjectTypeException, MBeanException, RuntimeOperationsException {
  23. if (resource == null) {
  24. throw new RuntimeOperationsException(new IllegalArgumentException("Managed resource is null"),
  25. "Managed resource is null");
  26. } else if (!"objectreference".equalsIgnoreCase(type)) {
  27. throw new InvalidTargetObjectTypeException(type);
  28. } else {
  29. this.resource = resource;
  30. }
  31. }

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. import javax.management.InstanceNotFoundException;
  4. import javax.management.MBeanException;
  5. import javax.management.MBeanServer;
  6. import javax.management.RuntimeOperationsException;
  7. import org.apache.catalina.Server;
  8. import org.apache.catalina.ServerFactory;
  9. import org.apache.catalina.core.StandardServer;
  10. import org.apache.commons.modeler.BaseModelMBean;
  11.  
  12. /**
  13. *
  14. * <p>
  15. * <b>Title:StandardServerMBean.java</b>
  16. * </p>
  17. * <p>
  18. * Copyright:ChenDong 2018
  19. * </p>
  20. * <p>
  21. * Company:仅学习时使用
  22. * </p>
  23. * <p>
  24. * 类功能描述: {@code org.apache.catalina.core.StandardServer} 组件的ModelMBean实现。
  25. * </p>
  26. *
  27. * @author 陈东
  28. * @date 2018年12月13日 下午7:36:09
  29. * @version 1.0
  30. */
  31.  
  32. public class StandardServerMBean extends BaseModelMBean {
  33.  
  34. // ------------------------------------------------------- Static Variables
  35.  
  36. /**
  37. * 应用程序的<code>MBeanServer</code> 组件
  38. */
  39. private static MBeanServer mserver = MBeanUtils.createServer();
  40.  
  41. // ----------------------------------------------------------- Constructors
  42.  
  43. /**
  44. *
  45. * 使用默认的<code>ModelMBeanInfo</code> 实现一个<code>ModelMBean</code>
  46. *
  47. * @exception MBeanException
  48. * 如果对象的初始化器引发异常
  49. * @exception RuntimeOperationsException
  50. *
  51. */
  52. public StandardServerMBean() throws MBeanException, RuntimeOperationsException {
  53.  
  54. super();
  55.  
  56. }
  57.  
  58. // ------------------------------------------------------------- Attributes
  59.  
  60. // ------------------------------------------------------------- Operations
  61.  
  62. /**
  63. *
  64. * 将整个<code>Server</code>的配置信息写入{@code server.xml}配置文件。
  65. *
  66. * @exception InstanceNotFoundException
  67. * 如果找不到托管资源对象
  68. * @exception MBeanException
  69. * 如果对象的初始化器抛出异常,或者不支持持久性
  70. * @exception RuntimeOperationsException
  71. * 如果持久性机制报告了异常
  72. */
  73. public synchronized void store() throws InstanceNotFoundException,
  74. MBeanException, RuntimeOperationsException {
  75.  
  76. Server server = ServerFactory.getServer();
  77. if (server instanceof StandardServer) {
  78. try {
  79. ((StandardServer) server).store();
  80. } catch (Exception e) {
  81. throw new MBeanException(e, "Error updating conf/server.xml");
  82. }
  83. }
  84.  
  85. }
  86.  
  87. }
  1. StandardServerMBean 是一种模型MBean,继承自BaseModelMBean,并重写了托管资源(org.apache.catalina.core.StandardServer)的一个方法

浅谈JMX的更多相关文章

  1. 浅谈springboot自动配置原理

    前言 springboot自动配置关键在于@SpringBootApplication注解,启动类之所以作为项目启动的入口,也是因为该注解,下面浅谈下这个注解的作用和实现原理 @SpringBootA ...

  2. 浅谈 Fragment 生命周期

    版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...

  3. 浅谈 LayoutInflater

    浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...

  4. 浅谈Java的throw与throws

    转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...

  5. 浅谈SQL注入风险 - 一个Login拿下Server

    前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...

  6. 浅谈WebService的版本兼容性设计

    在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...

  7. 浅谈angular2+ionic2

    浅谈angular2+ionic2   前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别.   1. 项目所用:angular2+ionic2 ...

  8. iOS开发之浅谈MVVM的架构设计与团队协作

    今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...

  9. Linux特殊符号浅谈

    Linux特殊字符浅谈 我们经常跟键盘上面那些特殊符号比如(?.!.~...)打交道,其实在Linux有其独特的含义,大致可以分为三类:Linux特殊符号.通配符.正则表达式. Linux特殊符号又可 ...

随机推荐

  1. MySQL优化相关参数--先做个记录,以后可能用得到

    innodb_io_capacity:可设置的磁盘IO性能参数,越高代表当前mysql的IO性能更好,可用做决策刷脏页速度的参数: innodb_flush_neighbors:刷脏页是否开启连坐机制 ...

  2. springboot项目的maven的pom.xml文件第一行报错 Unknown Error

    springboot项目的maven的pom.xml文件第一行报错 Unknown Error https://blog.csdn.net/mini_jike/article/details/9239 ...

  3. 查看MySQL 连接信息--连接空闲时间及正在执行的SQL

    MySQL 客户端与MySQL server建立连接后,就可以执行SQL语句了. 如何查看一个连接上是否正在执行SQL语句,或者连接是否处于空闲呢? 下面我们做下测试. 1.查看连接的空闲时间 首先看 ...

  4. LC 265. Paint House II

    There are a row of n houses, each house can be painted with one of the k colors. The cost of paintin ...

  5. Swagger介绍及使用

    相信无论是前端还是后端开发,都或多或少地被接口文档折磨过.前端经常抱怨后端给的接口文档与实际情况不一致.后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新.其实无论是前端调用后端,还是后端调用 ...

  6. vue-cli2.x版本安装vue-cli建项目

    全局安装vue-cli 命令行输入: vue-cli版本在3以下 npm install --global vue-cli 安装vue-cli后,可以查看一下是否安装成功vue --version, ...

  7. Spring-Kafka —— KafkaListener定时启动和停止

    一.定时启动的应用场景 比如现在单机环境下,我们需要利用Kafka做数据持久化的功能,由于用户活跃的时间为早上10点至晚上12点,那在这个时间段做一个大数据量的持久化可能会影响数据库性能导致用户体验降 ...

  8. Golang的goroutine协程和channel通道

    一:简介 因为并发程序要考虑很多的细节,以保证对共享变量的正确访问,使得并发编程在很多情况下变得很复杂.但是Go语言在开发并发时,是比较简洁的.它通过channel来传递数据.数据竞争这个问题在gol ...

  9. python字典操作+文件操作+函数

    师从百测besttest今天老牛教了些函数调用的知识,布置了个作业如下: # 1.写一个商品管理的小程序# 2.商品存在文件里面# 1.添加商品# 输入产品名称.颜色.价格# 要校验商品是否存在,价格 ...

  10. keepalived脑裂问题

    一.对脑裂的理解 在高可用(HA)系统中,当联系2个节点的“心跳线”断开时,本来为一整体.动作协调的HA系统,就分裂成为2个独立的个体.由于相互失去了联系,都以为是对方出了故障.两个节点上的HA软件像 ...