java - 在独立 JVM 上使用 Spring 注册 JMX MBean

标签 java spring jvm jmx

根据 Spring 文档以及互联网上一些论坛的各种示例配置,我的应用程序上下文文件如下所示:

<beans>
    <bean id="dH" class="abc.def.ghi.DH">
        <constructor-arg>
            <value>0</value>
        </constructor-arg>
        <property name="num" value="100"/>
    </bean>
    <bean class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
            <property name="beans">
              <map>
                    <entry key="bean:name=dH1" value-ref="dH"/>
              </map>
            </property>
    </bean>
    <bean class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
</beans>

我在没有任何容器的情况下在纯 JVM 上运行它。我可以通过 JConsole 连接到我的进程,但是 MBean 没有出现。但是,以编程方式注册 bean 会成功公开它。

MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
DH dh = new DH(0);
mbeanServer.registerMBean(dh, new ObjectName("bean:name=dH1"));

我试过使用 Spring 配置,但没有成功。我认为该 bean 没有注册到可以从 ManagementFactory.getPlatformMBeanServer() 访问的已经运行的 MBean 服务器。 关于这个问题有什么想法吗?

最佳答案

除了定义 MBeanServerFactory bean(如 Nicholas 在他们的 answer 中指出)使用 ...

<bean class="org.springframework.jmx.support.MBeanServerFactoryBean">
    <property name="locateExistingServerIfPossible" value="true" />
</bean>

...你需要告诉 MBeanExporter管理什么:

If a bean implements one of the JMX management interfaces, MBeanExporter can simply register the MBean with the server through its autodetection process.

If a bean does not implement one of the JMX management interfaces, MBeanExporter will create the management information using the supplied MBeanInfoAssembler.

假设您的 abc.def.ghi.DH 类没有实现任何 JMX 接口(interface),请尝试将您的 MBeanExporter 定义为:

<bean class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
    <property name="assembler">
        <bean
            class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler"
        >
            <property name="managedMethods">
                <list>
                    <value>getNum</value>
                </list>
            </property>
        </bean>
    </property>
    <property name="beans">
        <map>
            <entry key="bean:name=dH1" value-ref="dH"/>
        </map>
    </property>
</bean>

查看 OpenJDK 7,更新 2,构建 21 DefaultMBeanServerInterceptor.java source,第 898 行创建了一个 DynamicMBean对于常规对象:

DynamicMBean mbean = Introspector.makeDynamicMBean(object);

我没有调试它,但我打赌 mbeanServer.registerMBean(dh, new ObjectName("bean:name=dH1")) 最终会调用 DefaultMBeanServerInterceptor.registerObject(),它会为您创建一个 DynamicMBean 并正确注册您的标准 JavaBean 属性的 setter 和 getter。


以下是一些使用 Spring Framework 3.0.5 和 Oracle HotSpot Java 1.6.0_24 的测试文件。设置完 CLASSPATH 环境变量后,只需运行 javac *.javajava Main 并使用 VisualVM(或类似应用程序)连接到正在运行的java 应用程序以查看已注册的 MBean。

ac.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.xsd"
    default-lazy-init="true"
>
    <bean id="test" class="Test" />
    <bean class="org.springframework.jmx.support.MBeanServerFactoryBean">
        <property name="locateExistingServerIfPossible" value="true" />
    </bean>
    <bean class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
        <property name="assembler">
            <bean
                class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler"
            >
                <property name="managedMethods">
                    <list>
                        <value>getVal</value>
                        <value>setVal</value>
                    </list>
                </property>
            </bean>
        </property>
        <property name="beans">
            <map>
                <entry key="bean:name=Test" value-ref="test"/>
            </map>
        </property>
    </bean>
</beans>

测试.java:

public class Test {
    private String val = "";
    public String getVal() {
        return val;
    }
    public void setVal(String v) {
        val = v;
    }
}

主.java:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
    public static void main(final String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("ac.xml");
        try {
            Thread.sleep(1000 * 60 * 5);
        } catch (final Throwable t) {}
    }
}

关于java - 在独立 JVM 上使用 Spring 注册 JMX MBean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9163923/

相关文章:

java - 使用FactoryBean初始化的Bean接收FactoryBean而不是它创建的Obect

java - Spring 3的最小Hibernate 4 XML配置,用于基于注释的事务管理和对象映射?

java - 切换多个按钮可见性

Jetty 中的 javax.naming.NameNotFoundException 但 Tomcat 中没有。怎么解决?

java - Spring Boot 用户注册 - 将验证错误发送到 UI

java - Jvm 需要很长时间才能解析 localhost 的 ip 地址

java - String 是关于 switch 的数字类型并且总是编译为 lookupswitch 吗?

java - 为什么会跳过 for 循环?

java - 如何用 Java 打印 tar.gz 文件的内容?

java - 在 Entry<K, V> 类中使用 recordAccess(this)