Spring与JMX集成

 Spring与JMX集成,实现方式灵活而且简单,主要体现在:

1、可以自动探测实现MBean接口的MBean对象,而且可以将一个普通的Spring Bean注册为MBean;

2、定制管理MBean的接口,根据需要暴露特定管理MBean的操作;

3、使用注解定义MBean管理接口;

4、可以实现对本地和远程MBean的代理。

 

标准MBean管理

对于实现标准MBean接口MBean资源,在Spring中可以设置不同的探测模式,主要是通过MBeanExporter来实现。例如,定义MBean管理接口:

package org.shirdrn.spring.jmx.autodetect; public interface MyObjectMBean { public long getId(); public void setId(long id); public String getName(); public void setName(String name); public String show(); }

对应的MBean实现,如下所示:

package org.shirdrn.spring.jmx.autodetect; import org.apache.log4j.Logger; public class MyObject implements MyObjectMBean { private static final Logger LOG = Logger.getLogger(MyObject.class); private long id; private String name; public MyObject() { super(); } public MyObject(long id, String name) { super(); this.id = id; this.name = name; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String show() { StringBuffer sb = new StringBuffer().append("id=").append(id).append( ", name=").append(name); LOG.info("show()=" + sb.toString()); return sb.toString(); } }

上面是一个标准MBean的实现,可以使用JavaSE 6平台的JMX服务来管理,但是在Spring集成的环境下,也可以重用这些MBean实现,例如下面是一个典型的配置:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="mbServer" class="org.springframework.jmx.export.MBeanExporter"> <property name="autodetectModeName"> <value>AUTODETECT_ALL</value> </property> </bean> <bean name="mydomain:myobj=MyObjectMBean" class="org.shirdrn.spring.jmx.autodetect.MyObject"> <property name="id"> <value>90000000001</value> </property> <property name="name"> <value>shirdrn</value> </property> </bean> </beans>

上面配置中,MBeanExporter会查找本地MBean Server,指定的探测模式autodetectModeName为AUTODETECT_ALL,这也是MBeanExporter的默认值(这个属性完全可以省略,不用配置),无需手动向MBean Server进行注册,便能管理配置的MBean对象“mydomain:myobj=MyObjectMBean”。

对于探测模式autodetectModeName属性,Spring提供了4个取值:

AUTODETECT_NONE           不启用自动探测,需要手动向MBean Server进行注册,即通过MBeanExporter的beans属性进入注册;

AUTODETECT_MBEAN         在当前IOC容器中进行查找MBean组件;

AUTODETECT_ASSEMBLER  设置根据MBeanInfoAssembler的策略进行探测;

AUTODETECT_ALL               自动探测,是AUTODETECT_MBEAN和AUTODETECT_ASSEMBLER的并集。

另外,Spring的MBeanExporter也提供了autodetect属性,取值为true和false,指定对MBean组件的探测行为。

 

普通Spring Bean管理

对于一个普通的Spring Bean,也可以作为MBean来进行管理,Spring可以很好地支持。如下面一个普通的Java类:

package org.shirdrn.spring.jmx; import org.apache.log4j.Logger; public class MyJavaObject { private static final Logger LOG = Logger.getLogger(MyJavaObject.class); private long id; private String name; public MyJavaObject() { super(); } public MyJavaObject(long id, String name) { super(); this.id = id; this.name = name; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String show() { StringBuffer sb = new StringBuffer().append("id=").append(id).append( ", name=").append(name); LOG.info("show()=" + sb.toString()); return sb.toString(); } }

它并没有实现MBean管理接口,可以通过MBeanExporter的beans属性进行注册,配置如下所示:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="mbServer" class="org.springframework.jmx.export.MBeanExporter"> <property name="beans"> <map> <entry key="mydomain:myjavaobj=MyJavaObject" value-ref="myobj"/> </map> </property> </bean> <bean name="myobj" class="org.shirdrn.spring.jmx.MyJavaObject"> <property name="id"> <value>90000000001</value> </property> <property name="name"> <value>shirdrn</value> </property> </bean> </beans>

因为org.shirdrn.spring.jmx.MyJavaObject没有对应的MBean接口,所以默认情况下,该类中public的成员都会暴露出来,通过MBean Server可以管理。实际上,系统中MBean的某些属性或方法可能不需要暴露给外部进行管理,为了克服这种缺点,Spring提供了基于方法列表和接口定制的功能,可以将你所感兴趣的属性或方法暴露给外部管理。

 

基于方法列表和接口定制的MBean管理

对于上述普通的Java类MyJavaObject,可以通过定制接口和方法列表,来暴露MBean属性或方法。例如,一个方法列表,可以在进行配置的时候指定,如下所示:

<bean id="assembler" class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler"> <property name="managedMethods" value="setId,setName,show" /> </bean>

上面通过org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler来进行方法列表的设置。而对于接口,可以定义一个接口,如下所示:

package org.shirdrn.spring.jmx.selected.interfaces; public interface SelectedMethodsInterface { public long setId(long id); public void setName(String name); public void show(); }

Spring配置,如下所示:

<bean id="assembler" class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler"> <property name="managedInterfaces"> <list> <value>org.shirdrn.spring.jmx.selected.interfaces.SelectedMethodsInterface</value> </list> </property> </bean>

上面通过org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler,可以设置一个接口列表,来管理MBean暴露的接口。

对于上面两种方式,都得到一个assembler实例,需要将其注入到org.springframework.jmx.export.MBeanExporter中,如下所示:

<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> <property name="beans"> <map> <entry key="mydomain:javaObj=MyJavaObject" value-ref="javaObject" /> </map> </property> <property name="assembler" ref="assembler" /> </bean>

 

基于注解的MBean管理

对于一个普通的Java类,作为MBean需要被管理,可以通过注解指定要暴露的属性和方法,示例如下:

package org.shirdrn.spring.jmx.annotation; import org.apache.log4j.Logger; import org.springframework.jmx.export.annotation.ManagedAttribute; import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.annotation.ManagedResource; @ManagedResource(objectName = "annojmx:myjao=AnnotationObject", description = "MyJavaAnnotationObject") public class MyJavaAnnotationObject { private static final Logger LOG = Logger.getLogger(MyJavaAnnotationObject.class); private long id; private String name; public MyJavaAnnotationObject() { super(); } public MyJavaAnnotationObject(long id, String name) { super(); this.id = id; this.name = name; } @ManagedAttribute public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } @ManagedAttribute public void setName(String name) { this.name = name; } @ManagedOperation public String show() { StringBuffer sb = new StringBuffer().append("id=").append(id).append( ", name=").append(name); LOG.info("show()=" + sb.toString()); return sb.toString(); } }

上面@ManagedResource表示指定该类的实例作为MBean注册到MBean Server中,然后可以通过对属性和方法分别使用@ManagedAttribute和@ManagedOperation来指定暴露的属性和方法。有关这些注解的详细内容,可以查阅相关文档。

下面是一个基本的配置内容:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> <property name="assembler" ref="assembler" /> <property name="namingStrategy" ref="namingStrategy" /> </bean> <bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler"> <property name="attributeSource" ref="jmxas" /> </bean> <bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy"> <property name="attributeSource" ref="jmxas" /> </bean> <bean id="jmxas" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource" /> <bean id="javaObj" class="org.shirdrn.spring.jmx.annotation.MyJavaAnnotationObject"> <property name="id" value="201122121200" /> <property name="name" value="shirdrn" /> </bean> </beans>

上面使用了Spring的MBeanExporter,可以看到,Spring配置内容相对较多。

Spring还提供两种简化配置的方式,

一种是,提供了org.springframework.jmx.export.annotation.AnnotationMBeanExporter,可以将上述配置大大简化,等价的配置如下所示:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean class="org.springframework.jmx.export.annotation.AnnotationMBeanExporter"/> <bean name="myAnnoObject" class="org.shirdrn.spring.jmx.annotation.MyJavaAnnotationObject"> <property name="id" value="201122121200" /> <property name="name" value="shirdrn" /> </bean> </beans>

另一种是,提供了<context:mbean-export />标签,更加简洁,等价的配置如下所示:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:mbean-export registration="failOnExisting" /> <bean name="myAnnoObject" class="org.shirdrn.spring.jmx.annotation.MyJavaAnnotationObject"> <property name="id" value="201122121200" /> <property name="name" value="shirdrn" /> </bean> </beans>

 

通过远程代理访问MBean

根据JavaSE 6平台的JMX技术架构定义,分为设备层、代理层、远程管理层这三层,我们通过可以使用Spring提供的org.springframework.jmx.access.MBeanProxyFactoryBean实现,定义代理,来访问MBean Server管理MBean资源。实际上,Spring提供的这个代理功能位于JMX架构的远程管理层,那么在代理层和远程管理层之间,要定义连接器,才能通过远程管理层访问到代理层的MBean Server组件。下面通过实例来实现:

首先,定义个普通的Java类,作为待管理的MBean,如下所示:

package org.shirdrn.spring.jmx.rmi; import org.apache.log4j.Logger; public class MyJavaObject { private static final Logger LOG = Logger.getLogger(MyJavaObject.class); private long id; private String name; public MyJavaObject() { super(); } public MyJavaObject(long id, String name) { super(); this.id = id; this.name = name; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String show() { StringBuffer sb = new StringBuffer().append("id=").append(id).append( ", name=").append(name); LOG.info("show()=" + sb.toString()); return sb.toString(); } }

其次,定义了一个Java接口,来按需暴露操作MBean资源的方法:

package org.shirdrn.spring.jmx.rmi; public interface MyManagedInterfaces { public long setId(long id); public String getName(); public String show(); }

再次,看一下我们模拟代理层Spring配置server.xml内容:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> <property name="beans"> <map> <entry key="mydomain:myjavaobj=MyJavaObject" value-ref="myJavaObj" /> </map> </property> <property name="assembler" ref="assembler" /> </bean> <bean id="assembler" class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler"> <property name="managedInterfaces"> <list> <value>org.shirdrn.spring.jmx.rmi.MyManagedInterfaces</value> </list> </property> </bean> <bean name="myJavaObj" class="org.shirdrn.spring.jmx.rmi.MyJavaObject"> <property name="id" value="88000000001" /> <property name="name" value="shirdrn" /> </bean> <bean id="server" class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="registry"> <property name="objectName"> <value>connector:name=rmi</value> </property> <property name="serviceUrl"> <value>service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxrmi</value> </property> </bean> <bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"> <property name="port"> <value>1099</value> </property> </bean> </beans>

上半部分配置已经非常熟悉,就是将MBean注册到MBean Server中。下半部分是有关连接器的配置,它是基于RMI协议来进行适配,通过Spring提供的org.springframework.jmx.support.ConnectorServerFactoryBean来实现器,这样,远程管理层可以连接到启动的连接服务器,来访问MBean资源。

然后,我们启动MBean Server及其连接服务器,代码如下所示:

package org.shirdrn.spring.jmx.rmi; import org.apache.log4j.Logger; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Server { private static final Logger LOG = Logger.getLogger(Server.class); public static void main(String[] args) throws Exception { new ClassPathXmlApplicationContext("org/shirdrn/spring/jmx/rmi/server.xml"); LOG.info("Server started."); Object lock = new Object(); synchronized (lock) { lock.wait(); } } }

启动后,我们定义的MBean已经注册到本地MBean Server中,同时启动了连接器,监听1099端口。

接着,我们定义远程访问层的Spring配置proxy.xml内容,如下所示:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="proxy" class="org.springframework.jmx.access.MBeanProxyFactoryBean"> <property name="connectOnStartup" value="true" /> <property name="objectName" value="mydomain:myjavaobj=MyJavaObject" /> <property name="proxyInterface"> <value>org.shirdrn.spring.jmx.rmi.MyManagedInterfaces</value> </property> <property name="serviceUrl"> <value>service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxrmi</value> </property> </bean> </beans>

最后,启动代理,访问MBean资源,代码如下所示:

package org.shirdrn.spring.jmx.rmi; import org.apache.log4j.Logger; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Proxy { private static final Logger LOG = Logger.getLogger(Proxy.class); public static void main(String[] args) throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext( "org/shirdrn/spring/jmx/rmi/proxy.xml"); LOG.info("Proxy server started."); MyManagedInterfaces proxy = (MyManagedInterfaces) ctx.getBean("proxy"); String message = proxy.show(); LOG.info("proxy.show() = " + message); Object lock = new Object(); synchronized (lock) { lock.wait(); } } }

这里,只能访问通过org.shirdrn.spring.jmx.rmi.MyManagedInterfaces接口定义的方法来操作注册到MBean Server中的MBean资源。

你可能感兴趣的:(spring,bean,String,Class,jmx,encoding)