扩展 Spring 的 JMX 支持(1)(3)

2008-02-23 08:12:13来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折



  MBeanInfo 模型

  如果下载与本文有关的代码,您会发现一个名为 com.claudeduguay.mbeans.model 的包,它包含一组用于建模 MBeanInfo XML 文件的类。这个包包含大量类,因此我不会详细讨论所有类,但是其基本内容还是有必要说明的。

  模型的根是 MBeanDescriptor 类,它提供了一个 createMBeanInfo() 方法,负责用应用程序元数据创建一个兼容 JMX 的 ModelMBeanInfo 实例。MBeanDescriptorUtil 类提供了两个静态的 read() 方法,它装载并保存这个 XML 文档模型。这个模型中使用的 Document 和 Element 实例基于 JDOM 框架。

  我使用的基本 MBeanInfo 相关类和描述符模型是密切相关的。基类中的所有基本属性都是在 XML 中建模的,并可以用简单的格式定义。例如,<mbean> 标记是我的文档的根。它与 ModelMBeanInfo 直接相关,它期待一个 typedescription 属性。类型是受管 bean 的完全限定类名。不过,在使用我的 Sping 解决方案时,这个类完全可以在上下文中派生。<mbean> 标记期待零个或者多个 attributeoperationconstructornotification 子类型。它们每一个都提供了基 MBeanInfo 类 XML 属性。

图 1. MBean XML 格式


  MBean 模型实现利用了 com.claudeduguay.util.jdom 包中几个与 JDOM 相关的工具类。它们主要是解析和构建 Document 和 Element 对象的接口,一个工具类使读和写 Document 流更容易。要查看的大多数代码在 com.claudeduguay.mbeans.spring 包中。

  已经做了足够的预备工作,让我们开始扩展 Spring JMX!

  改进 ModelMBean 中的通知

  我要做的第一件事是扩展 Spring JMX ModelMBean 实现,这样就可以发送通知而不用在管理的资源中直接实现这个行为。为此,还需要扩展 Spring 导出器以创建改进的 ModelMBean 实例。最后,还需要用一个新的装配器从映射文件中提取 MBeanInfo 元数据。

  ModelMBeanExtension 类

  扩展 RequiredModelMBean 类的一个目的是在管理代理中透明地启用通知。这个应用程序需要三种通知:设置属性值、方法调用之前以及方法调用之后。因为消息是我自己配置的,在每一种情况下,它都可以按照我需要的那样提供信息。要实现这一点,我对类型通知使用了一个命名规范,其中对于样式 <matchingType>.<methodOrAttributeName> 检查点分隔的类型名。匹配的类型必须为 set、before 或者 after 之一。如果类型是 set,那么就认为是一个属性名,否则,就认为是一个方法名。

  扩展的 ModelMBean 代码使用额外的类帮助进行耦合。第一个是 NotificationInfoMap,它是一个用通知元数据构建的、简单的 Map,并与前缀(set|before|after)点名(method|attribute)样式相关联,这样就可以更有效地得到匹配的通知元数据。第二个是工具方法的一个静态集合。清单 1 显示了为通知而扩展的 RequiredModelMBean:

清单 1. ModelMBeanExtension

 

     

package com.claudeduguay.mbeans.spring; 



import java.lang.reflect.*; 



import javax.management.*; 

import javax.management.modelmbean.*; 



public class ModelMBeanExtension extends RequiredModelMBean 

{ 

  protected NotificationInfoMap notificationInfoMap; 

  protected ModelMBeanInfo modelMBeanInfo; 

  protected Object managedBean; 

   

  public ModelMBeanExtension() throws MBeanException {} 



  public ModelMBeanExtension(ModelMBeanInfo modelMBeanInfo) 

    throws MBeanException 

  { 

    super(modelMBeanInfo); 

    this.modelMBeanInfo = modelMBeanInfo; 

    notificationInfoMap = new NotificationInfoMap(modelMBeanInfo); 

  } 

   

  public void setModelMBeanInfo(ModelMBeanInfo modelMBeanInfo) 

    throws MBeanException 

  { 

    this.modelMBeanInfo = modelMBeanInfo; 

    notificationInfoMap = new NotificationInfoMap(modelMBeanInfo); 

    super.setModelMBeanInfo(modelMBeanInfo); 

  } 

   

  public MBeanNotificationInfo[] getNotificationInfo() 

  { 

    return modelMBeanInfo.getNotifications(); 

  } 

   

  public void setManagedResource(Object managedBean, String type) 

    throws MBeanException, RuntimeOperationsException, 

      InstanceNotFoundException, InvalidTargetObjectTypeException 

  { 

    super.setManagedResource(managedBean, type); 

    this.managedBean = managedBean; 

  } 

   

  protected void maybeSendMethodNotification( 

   String type, String name) throws MBeanException 

  { 

    MBeanNotificationInfo info = notificationInfoMap. 

      findNotificationInfo(type, name); 

    if (info != null) 

    { 

      long timeStamp = System.currentTimeMillis(); 

      String notificationType = ModelMBeanUtil. 

        matchType(info, "."   type   "."   name); 

      sendNotification(new Notification( 

        notificationType, this, timeStamp, 

        info.getDescription())); 

    } 

  } 



  protected void maybeSendAttributeNotification( 

    Attribute attribute) 

    throws MBeanException, AttributeNotFoundException, 

    InvalidAttributeValueException, ReflectionException 

  { 

    String name = attribute.getName(); 

    MBeanNotificationInfo info = notificationInfoMap. 

      findNotificationInfo("set", attribute.getName()); 

    if (info != null) 

    { 

      Object oldValue = getAttribute(name); 

      Object newValue = attribute.getValue(); 

      long timeStamp = System.currentTimeMillis(); 

      String notificationType = ModelMBeanUtil. 

        matchType(info, ".set."   name); 

      sendNotification(new AttributeChangeNotification( 

        this, timeStamp, timeStamp, 

        info.getDescription(), info.getName(), 

        notificationType, oldValue, newValue)); 

    } 

  } 

   

  public Object invoke( 

   String name, Object[] args, String[] signature) 

      throws MBeanException, ReflectionException 

  { 

    maybeSendMethodNotification("before", name); 

    Object returnValue = super.invoke(name, args, signature); 

    maybeSendMethodNotification("after", name); 

    return returnValue; 

  } 



  public Object getAttribute(String name) throws MBeanException, 

    AttributeNotFoundException, ReflectionException 

  { 

    try 

    { 

      Method method = ModelMBeanUtil.findGetMethod( 

        modelMBeanInfo, managedBean, name); 

      return method.invoke(managedBean, new Object[] {}); 

    } 

    catch (IllegalAccessException e) 

    { 

      throw new MBeanException(e); 

    } 

    catch (InvocationTargetException e) 

    { 

      throw new MBeanException(e); 

    } 

  } 



  public void setAttribute(Attribute attribute) 

    throws MBeanException, AttributeNotFoundException, 

      InvalidAttributeValueException, ReflectionException 

  { 

    try 

    { 

      Method method = ModelMBeanUtil.findSetMethod( 

        modelMBeanInfo, managedBean, attribute.getName()); 

      method.invoke(managedBean, attribute.getValue()); 

      maybeSendAttributeNotification(attribute); 

    } 

    catch (InvocationTargetException e) 

    { 

      throw new MBeanException(e); 

    } 

    catch (IllegalAccessException e) 

    { 

      throw new MBeanException(e); 

    } 

  } 

} 

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Swing是MVC设计的典范

下一篇:扩展 Spring 的 JMX 支持(2)