首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

扩展 Spring 的 JMX 支持(4)

扩展 Spring 的 JMX 支持(4)

扩展 Spring JMX 导出器为了使用扩展的 ModelMBean,需要覆盖 Spring MBeanExporter 中的 createModelMBean() 方法。因为可以注入装配器属性,所以必须知道它可能不是我所期待的这一事实。可以在构造函数中设置所需要的装配器,但是当装配器改变时需要返回一个普通 ModelMBean。所要做的就是缓存一个 MBeanInfoAssembler 的本地引用,并在创建新的 ModelMBean 时检查它是什么类型的。清单 2 显示了所有这些改变:
清单 2. MBeanDescriptorEnabledExporter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.claudeduguay.mbeans.spring;
import javax.management.*;
import javax.management.modelmbean.*;
import org.springframework.jmx.export.*;
import org.springframework.jmx.export.assembler.*;
public class MBeanDescriptorEnabledExporter extends MBeanExporter
{
  protected MBeanInfoAssembler mBeanInfoAssembler;
   
  public MBeanDescriptorEnabledExporter()
  {
    setAssembler(new MBeanDescriptorBasedAssembler());
  }
   
  public ModelMBean createModelMBean() throws MBeanException
  {
    if (mBeanInfoAssembler instanceof MBeanDescriptorBasedAssembler)
    {
      return new ModelMBeanExtension();
    }
    return super.createModelMBean();
  }
   
  public void setAssembler(MBeanInfoAssembler mBeanInfoAssembler)
  {
    this.mBeanInfoAssembler = mBeanInfoAssembler;
    super.setAssembler(mBeanInfoAssembler);
  }
}




在使用这个扩展的类时,可以用标准 Spring 语言改变装配器,并在需要时回到默认的行为。在大多数情况下,如果最终绕过扩展,那么就不值得使用这个版本。不过,如果想要以新的定制装配器使用扩展的 ModelMBean,那么现在可以这样做。
构建一个定制的装配器这个定制装配器的主要任务是查找与管理的类有关的元数据映射文件。找到这个文件后,就装载它并生成必要的 ModelMBeanInfo 实例。为此,我只是实现了 Spring MBeanInfoAssembler 实例建立这个文件的相关类路径,用静态MBeanDescriptorUtil.read() 方法装载它并返回结果,如清单 3 所示:
清单 3. MBeanDescriptorBasedAssembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.claudeduguay.mbeans.spring;
import java.io.*;
import javax.management.modelmbean.*;
import org.springframework.core.io.*;
import org.springframework.jmx.export.assembler.*;
import com.claudeduguay.mbeans.model.*;
public class MBeanDescriptorBasedAssembler
  implements MBeanInfoAssembler
{
  public ModelMBeanInfo getMBeanInfo(
    Object managedBean, String beanKey)
  {
    String name = managedBean.getClass().getName();
    String path = name.replace('.', '/') + ".mbean.xml";
     
    ClassPathResource resource = new ClassPathResource(path);
    InputStream input = null;
    try
    {
      input = resource.getInputStream();
      MBeanDescriptor descriptor = MBeanDescriptorUtil.read(input);
      return descriptor.createMBeanInfo();
    }
    catch (Exception e)
    {
      throw new IllegalStateException(
        "Unable to load resource: " + path);
    }
    finally
    {
      if (input != null)
      {
        try { input.close(); } catch (Exception x) {}
      }
    }
  }
}




这个 MBeanDescriptorBasedAssembler 忽略 bean 键参数并直接用受管 bean 引用创建所需的 ModelMBeanInfo 实例。
示例在本文其余部分,我将着重展示这个 Spring JMX 扩展的使用。为此,使用一个假想的服务,它开放两个方法和一个属性,因此表现了典型的用例。
ExampleService 是一个 Java 对象,它在被调用时只是向控制台进行输出,如清单 4 所示:
清单 4. ExampleService
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.claudeduguay.jmx.demo.server;
public class ExampleService
{
  protected String propertyValue = "default value";
   
  public ExampleService() {}
   
  public String getPropertyValue()
  {
    System.out.println("ExampleService: Get Property Value");
    return propertyValue;
  }
  public void setPropertyValue(String propertyValue)
  {
    System.out.println("ExampleService: Set Property Value");
    this.propertyValue = propertyValue;
  }
  public void startService()
  {
    System.out.println("ExampleService: Start Service Called");
  }
  public void stopService()
  {
    System.out.println("ExampleService: Stop Service Called");
  }
}




对管理员友好的消息这个扩展的描述符可以几乎直接关联属性和操作。描述符方法优于内省式方法的主要一点是可以提供更特定的消息。通知描述符的配置选项有赖于类型(XML)属性的命名规范。实际的名字是任意的,但是代码会被类型中的 set.name、before.name 和 after.name 样式触发。在这种情况下,我将 set 通知与 propertyValue (JMX)属性关联,将 before 与 after 通知与 startService() 与 stopService() 方法关联。同样,这些扩展使我可以很好利用描述性的消息。
在清单 5 中,可以看到定义了一个属性和两个方法。通知描述符定义了方法的之前和之后事件以及一个属性设置通知:
清单 5. ExampleService.mbean.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0"?>
<mbean name="ExampleService" description="Example Service"
  type="com.claudeduguay.jmx.demo.server.ExampleService">
  <attribute name="propertyValue"
    description="Property Value Access" type="java.lang.String"
    readable="true" writable="true" />
  <operation name="stopService"
    description="Stop Example Service" />
  <operation name="startService"
    description="Start Example Service" />
  <notification name="PropertyValueSet"
    types="example.service.set.propertyValue"
    description="PropertyValue was set" />
  <notification name="BeforeStartService"
    types="example.service.before.startService"
    description="Example Service is Starting" />
  <notification name="AfterStartService"
    types="example.service.after.startService"
    description="Example Service is Started" />
  <notification name="BeforeStopService"
    types="example.service.before.stopService"
    description="Example Service is Stopping" />
  <notification name="AfterStopService"
    types="example.service.after.stopService"
    description="Example Service is Stopped" />
   
</mbean>

返回列表