扩展 Spring 的 JMX 支持
扩展 Spring JMX 导出器
为了使用扩展的 ModelMBean,需要覆盖 Spring MBeanExporter 中的 createModelMBean() 方法。因为可以注入装配器属性,所以必须知道它可能不是我所期待的这一事实。可以在构造函数中设置所需要的装配器,但是当装配器改变时需要返回一个普通 ModelMBean。所要做的就是缓存一个 MBeanInfoAssembler 的本地引用,并在创建新的 ModelMBean 时检查它是什么类型的。清单 2 显示了所有这些改变:
清单 2. MBeanDescriptorEnabledExporter
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
这个 MBeanDescriptorBasedAssembler 忽略 bean 键参数并直接用受管 bean 引用创建所需的 ModelMBeanInfo 实例。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) ...{}
}
}
}
}
示例
在本文其余部分,我将着重展示这个 Spring JMX 扩展的使用。为此,使用一个假想的服务,它开放两个方法和一个属性,因此表现了典型的用例。
ExampleService 是一个 Java 对象,它在被调用时只是向控制台进行输出,如清单 4 所示:
清单 4. ExampleService
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");
}
}
0
相关文章
