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); } } |
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
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 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> |
配置服务器
要在客户机/服务器环境中运行这个例子,需要配置和启动一个 mbeanserver 实例。为此,我使用 java 5.0 mbeanserver 实例,它保证我可以使用 jvm 中提供的管理扩展,同时管理自己的代码。如果愿意,还可以运行 mbeanserver 的多个实例,您愿意的话也可以自己试一试作为练习。
就像 java 5.0 一样,spring 框架使您可以配置自己的 mbeanserver 实例。我选择使用 java 5.0,因为它支持 jsr-160 连接器,我的客户机代码会需要它。
清单 6. springjmxserver
package com.claudeduguay.jmx.demo.server; import org.springframework.context.*; import org.springframework.context.support.*; import mx4j.tools.adaptor.http.*; /* * to use the springjmxserver, use the following command line * arguments to activate the java 1.5 jmx server. * * -dcom.sun.management.jmxremote.port=8999 * -dcom.sun.management.jmxremote.ssl=false * -dcom.sun.management.jmxremote.authenticate=false */ public class springjmxserver { public static void main(string[] args) throws exception { string spring_file = "com/claudeduguay/jmx/demo/server/springjmxserver.xml"; applicationcontext context = new classpathxmlapplicationcontext(spring_file); httpadaptor httpadaptor = (httpadaptor)context.getbean("httpadaptor"); httpadaptor.start(); } } |
<?xml version="1.0" encoding="utf-8"?> <!doctype beans public "-//spring//dtd bean//en" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="exporter" class= "com.claudeduguay.mbeans.spring.mbeandescriptorenabledexporter"> <property name="beans"> <map> <entry key="services:name=exampleservice" value-ref="exampleservice" /> <entry key="mx4j:name=httpadaptor" value-ref="httpadaptor" /> <entry key="mx4j:name=xsltprocessor" value-ref="xsltprocessor" /> </map> </property> </bean> <bean id="xsltprocessor" class="mx4j.tools.adaptor.http.xsltprocessor" /> <bean id="httpadaptor" class="mx4j.tools.adaptor.http.httpadaptor"> <property name="processor" ref="xsltprocessor"/> <property name="port" value="8080"/> </bean> <bean id="exampleservice" class="com.claudeduguay.jmx.demo.server.exampleservice" /> </beans> |
package com.claudeduguay.jmx.demo.client; import java.util.*; import javax.management.*; import javax.management.remote.*; public class springjmxclient implements notificationlistener { public void handlenotification( notification notification, object handback) { system.out.println( "notification: " + notification.getmessage()); } public static void main(string[] args) throws exception { springjmxclient listener = new springjmxclient(); string address = "service:jmx:rmi:///jndi/rmi://localhost:8999/jmxrmi"; jmxserviceurl serviceurl = new jmxserviceurl(address); map<string,object> environment = null; jmxconnector connector = jmxconnectorfactory.connect(serviceurl, environment); mbeanserverconnection mbeanconnection = connector.getmbeanserverconnection(); objectname exampleservicename = objectname.getinstance("services:name=exampleservice"); mbeanconnection.addnotificationlistener( exampleservicename, listener, null, null); mbeanconnection.invoke( exampleservicename, "startservice", null, null); mbeanconnection.setattribute(exampleservicename, new attribute("propertyvalue", "new value")); system.out.println(mbeanconnection.getattribute( exampleservicename, "propertyvalue")); mbeanconnection.invoke( exampleservicename, "stopservice", null, null); } } |
新闻热点
疑难解答