?
Spring集成JMX是很简单的,这里通过注解发方式暴露JMX,有的时序我们需要监听JMX属性的改变,下面我们在Spring配置文件中配置监听器。
?
涉及到三个重要的annotation:@ManagedResource @ManagedAttribute 和 @ManagedOperation。
用途 Commons Attributes属性 JDK 5.0注解 属性/注解类型
将类的所有实例标识为JMX受控资源 | ManagedResource |
@ManagedResource |
Class 类 |
将方法标识为JMX操作 | ManagedOperation |
@ManagedOperation |
Method方法 |
将getter或者setter标识为部分JMX属性 | ManagedAttribute |
@ManagedAttribute |
Method (only getters and setters) 方法(仅getters和setters) |
定义操作参数说明 | ManagedOperationParameter |
@ManagedOperationParameter 和@ManagedOperationParameters
|
Method 方法 |
?
ObjectName | Used by MetadataNamingStrategy to determine the ObjectName of a managed resource | ManagedResource |
description | Sets the friendly description of the resource, attribute or operation | ManagedResource, ManagedAttribute, ManagedOperation, ManagedOperationParameter |
currencyTimeLimit | Sets the value of the currencyTimeLimit descriptor field | ManagedResource, ManagedAttribute |
defaultValue | Sets the value of the defaultValue descriptor field | ManagedAttribute |
log | Sets the value of the log descriptor field | ManagedResource |
logFile | Sets the value of the logFile descriptor field | ManagedResource |
persistPolicy | Sets the value of the persistPolicy descriptor field | ManagedResource |
persistPeriod | Sets the value of the persistPeriod descriptor field | ManagedResource |
persistLocation | Sets the value of the persistLocation descriptor field | ManagedResource |
persistName | Sets the value of the persistName descriptor field | ManagedResource |
name | Sets the display name of an operation parameter | ManagedOperationParameter |
index | Sets the index of an operation parameter | ManagedOperationParameter |
?AttributeChangeNotification,这个类是javax.management.Notification的子类,而javax.management.Notification
这个类又是java.util.EventObject的子类,由此可以证实上边所说的,JMX通知机制使用了观察者设计模式.
?
javax.management.Notification是一个JMX的通知核心类,将来需要扩展或者其他JMX自带的消息,均集成自此类.
?
AttributeChangeNotification根据类名可知,是一个属性改变的通知,造方法参数如下:
?
?
Object source, ? ? ? ? ? ? ? ? // 事件源,一直传递到java.util.EventObject的source
long sequenceNumber, ? // 通知序号,标识每次通知的计数器
long timeStamp, ? ? ? ? ? ? ?// 通知发出的时间戳?
String msg, ? ? ? ? ? ? ? ? ? ? // 通知发送的message
String attributeName, ? ? // 被修改属性名
String attributeType, ? ? ?// 被修改属性类型
Object oldValue, ? ? ? ? ? ? // 被修改属性修改以前的值
Object newValue ? ? ? ? ? ?// 被修改属性修改以后的值
?
?
根据观察者模式,由事件与广播组成,所以这里继承了NotificationBroadcasterSupport,来提供广播机制,
?
调用NotificationBroadcasterSupportr的sendNotification(notification) 发送广播,广播会根据注册的观察者
?
来对观察者进行逐一通知.
/** * * @author Lenovo * @version $Id: HelloMBean.java, v 0.1 2014年9月26日 下午4:28:17 Lenovo Exp $ */ @Component @ManagedResource(description = "hello demo", objectName = "bean:name=helloTest") public class Hello extends NotificationBroadcasterSupport implements HelloMBean { private final String name = "Reginald"; private int cacheSize = DEFAULT_CACHE_SIZE; private static final int DEFAULT_CACHE_SIZE = 200; private long sequenceNumber = 1; /** * @see com.cathy.demo.jmx.notifications.HiMBean#sayHello() */ @ManagedOperation(description = "say hello") public void sayHello() { System.out.println("Hello,Word"); } /** * @see com.cathy.demo.jmx.notifications.HiMBean#add(int, int) */ @ManagedOperation(description = "add") @ManagedOperationParameters({ @ManagedOperationParameter(name = "x", description = "fist param"), @ManagedOperationParameter(name = "y", description = "second param") }) public int add(int x, int y) { return x + y; } /** * 获取 name 属性,通过gatter 方法获取私有的成员属性,在这个例子中属性值是永远不会改变的;但是对于其他的属性可能在程序的运行期间进行 * 改变。然而一些属性代表统计数据,如,如运行时间,内存使用情况等是只读到 也就是不能通过接口改变的 * @see com.cathy.demo.jmx.notifications.HiMBean#getName() */ @ManagedAttribute public String getName() { return name; } /** * 获取私有成员变量cacheSize 的值 * @see com.cathy.demo.jmx.notifications.HiMBean#getCacheSize() */ @ManagedAttribute public int getCacheSize() { return cacheSize; } /** * 设置私有成员变量cacheSize 的值 * @see com.cathy.demo.jmx.notifications.HiMBean#setCacheSize(int) */ @ManagedAttribute public void setCacheSize(int size) { int oldSize = cacheSize; System.out.println("Cache size now is " + oldSize); /** * 构建一个介绍属性改变的通知, */ Notification notification = new AttributeChangeNotification(this, sequenceNumber++, System.currentTimeMillis(), "CacheSize changed", "cacheSize", "int", oldSize, size); /** * 发送通知 */ sendNotification(notification); cacheSize = size; } /** * @see javax.management.NotificationBroadcasterSupport#getNotificationInfo() */ @Override public MBeanNotificationInfo[] getNotificationInfo() { String[] types = new String[] { AttributeChangeNotification.ATTRIBUTE_CHANGE }; String name = AttributeChangeNotification.class.getName(); String description = "An attribute of this MBean has changed"; MBeanNotificationInfo info = new MBeanNotificationInfo(types, name, description); return new MBeanNotificationInfo[] { info }; } }
通知监听器:
?
?
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:task="http://www.springframework.org/schema/task" xmlns:util="http://www.springframework.org/schema/util" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd "> <aop:aspectj-autoproxy /> <context:annotation-config /> <context:component-scan base-package="com.cathy.demo.jmx.*" /> <bean id="jmxAttributeSource" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource" /> <bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler"> <property name="attributeSource" ref="jmxAttributeSource" /> </bean> <!-- ObjectName命名策略 --> <bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy"> <property name="attributeSource" ref="jmxAttributeSource" /> </bean> <bean id="mbeanExporter" class="org.springframework.jmx.export.MBeanExporter"> <!-- 指定messageInfo装配类 --> <property name="assembler" ref="assembler" /> <!-- 指定ObjectName命名策略 --> <property name="namingStrategy" ref="namingStrategy" /> <!-- 配置自动检测MBean --> <property name="autodetect" value="true" /> <property name="notificationListenerMappings"> <map> <entry key="*"> <bean class="com.cathy.demo.jmx.listener.ConfigNotificationListener" /> </entry> </map> </property> </bean> <bean id="fileReplicator" class="com.cathy.demo.jmx.annotation.FileReplicatorImpl" /> </beans>
?
?
/** * * @author zhangwei_david * @version $Id: ConfigNotificationListener.java, v 0.1 2015年6月19日 下午4:37:09 zhangwei_david Exp $ */ public class ConfigNotificationListener implements NotificationListener, NotificationFilter { /** */ private static final long serialVersionUID = 1099818764372891903L; /** * @see javax.management.NotificationListener#handleNotification(javax.management.Notification, java.lang.Object) */ public void handleNotification(Notification notification, Object handback) { log("SequenceNumber:" + notification.getSequenceNumber()); log("Type:" + notification.getType()); log("Message:" + notification.getMessage()); log("Source:" + notification.getSource()); log("TimeStamp:" + notification.getTimeStamp()); } private void log(String message) { System.out.println(message); } /** * @see javax.management.NotificationFilter#isNotificationEnabled(javax.management.Notification) */ public boolean isNotificationEnabled(Notification notification) { return true; } }
?通过Jconsole控制台可以看到如下信息:
?修改cacheSize?在eclipse的控制台可以看到如下日志:
?
?
log4j:WARN custom level class [# 输出DEBUG级别以上的日志] not found. 2015-06-21 13:42:55 [ main:0 ] - [ INFO ] @TestExecutionListeners is not present for class [class com.cathy.demo.jmx.AutoDetectJmxTest]: using defaults. 2015-06-21 13:42:56 [ main:137 ] - [ INFO ] Loading XML bean definitions from URL [file:/H:/Alipay.com/workspace4alipay/demo/target/classes/META-INF/spring/jmx-annotation-beans.xml] 2015-06-21 13:42:56 [ main:369 ] - [ INFO ] JSR-250 ‘javax.annotation.ManagedBean‘ found and supported for component scanning 2015-06-21 13:42:56 [ main:421 ] - [ INFO ] Refreshing org.springframework.context.support.GenericApplicationContext@15f7ae5: startup date [Sun Jun 21 13:42:56 CST 2015]; root of context hierarchy 2015-06-21 13:42:56 [ main:580 ] - [ INFO ] Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@40cd94: defining beans [org.springframework.aop.config.internalAutoProxyCreator,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,hello,jmxAttributeSource,assembler,namingStrategy,mbeanExporter,fileReplicator,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy 2015-06-21 13:42:56 [ main:693 ] - [ INFO ] Registering beans for JMX exposure on startup 2015-06-21 13:42:56 [ main:695 ] - [ INFO ] Bean with name ‘hello‘ has been autodetected for JMX exposure 2015-06-21 13:42:56 [ main:705 ] - [ INFO ] Bean with name ‘fileReplicator‘ has been autodetected for JMX exposure 2015-06-21 13:42:56 [ main:707 ] - [ INFO ] Located MBean ‘hello‘: registering with JMX server as MBean [bean:name=helloTest] 2015-06-21 13:42:56 [ main:709 ] - [ INFO ] Located managed bean ‘fileReplicator‘: registering with JMX server as MBean [com.cathy.demo.jmx.annotation:name=fileReplicator,type=FileReplicatorImpl] Cache size now is 200 SequenceNumber:1 Type:jmx.attribute.change Message:CacheSize changed Source:bean:name=helloTest TimeStamp:1434865528473
?
原文:http://zhangwei-david.iteye.com/blog/2221097