JMX之将Spring Bean 输出为带通知的MBean

Tags: java spring

Spring集成JMX是很简单的,这里通过注解发方式暴露JMX,有的时序我们需要监听JMX属性的改变,下面我们在Spring配置文件中配置监听器。

涉及到三个重要的annotation:@ManagedResource @ManagedAttribute 和 @ManagedOperation。

用途 Commons Attributes属性 JDK 5.0注解 属性/注解类型

将类的所有实例标识为JMX受控资源ManagedResource@ManagedResourceClass 类
将方法标识为JMX操作ManagedOperation@ManagedOperationMethod方法
将getter或者setter标识为部分JMX属性ManagedAttribute@ManagedAttributeMethod (only getters and setters) 方法(仅getters和setters)
定义操作参数说明ManagedOperationParameter@ManagedOperationParameter@ManagedOperationParametersMethod 方法
/**
 *
 * @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://www.4byte.cn/learning/119870/jmx-zhi-jiang-spring-bean-shu-chu-wei-dai-tong-zhi-de-mbean.html