将你的 Bean 导出到 JMX
Spring JMX 框架中的核心类是 MBeanExporter
。这个类负责获取你的 Spring bean
并将其注册到 JMX MBeanServer
。例如,考虑以下类:
include-code::./JmxTestBean[tag=snippet,indent=0]
要将此 bean 的属性和方法作为 MBean 的属性和操作公开,你可以在配置文件中配置
MBeanExporter
类的一个实例,并将 bean 传递进去,如以下示例所示:
include-code::./JmxConfiguration[tag=snippet,indent=0]
前面配置片段中相关的 bean 定义是 exporter
bean。beans
属性告诉
MBeanExporter
哪些 bean 必须导出到 JMX MBeanServer
。在默认配置中,
beans
Map
中每个条目的键用作相应条目值引用的 bean 的 ObjectName
。
你可以更改此行为,如 控制你的 Bean 的 ObjectName
实例 中所述。
通过此配置,testBean
bean 作为 ObjectName
bean:name=testBean1
下的
MBean 公开。默认情况下,bean 的所有 public
属性都作为属性公开,所有
public
方法(除了那些从 Object
类继承的方法)都作为操作公开。
|
创建 MBeanServer
上一节 中显示的配置假定应用程序在已经有一个(且只有一个)
MBeanServer
正在运行的环境中运行。在这种情况下,Spring 尝试定位正在运行的 MBeanServer
并将你的 bean 注册到该服务器(如果有)。当你的应用程序在具有自己的
MBeanServer
的容器(例如 Tomcat 或 IBM WebSphere)中运行时,此行为很有用。
然而,这种方法在独立环境中或在不提供 MBeanServer
的容器中运行时没有用。
为了解决这个问题,你可以通过在配置中添加 org.springframework.jmx.support.MBeanServerFactoryBean
类的一个实例来声明性地创建一个 MBeanServer
实例。你还可以通过将
MBeanExporter
实例的 server
属性值设置为 MBeanServerFactoryBean
返回的 MBeanServer
值来确保使用特定的 MBeanServer
,如以下示例所示:
<beans>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
<!--
this bean needs to be eagerly pre-instantiated in order for the exporting to occur;
this means that it must not be marked as lazily initialized
-->
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="bean:name=testBean1" value-ref="testBean"/>
</map>
</property>
<property name="server" ref="mbeanServer"/>
</bean>
<bean id="testBean" class="org.springframework.jmx.JmxTestBean">
<property name="name" value="TEST"/>
<property name="age" value="100"/>
</bean>
</beans>
在前面的示例中,MBeanServerFactoryBean
创建了一个 MBeanServer
实例,
并通过 server
属性提供给 MBeanExporter
。当你提供自己的 MBeanServer
实例时,
MBeanExporter
不会尝试定位正在运行的 MBeanServer
,而是使用提供的 MBeanServer
实例。
为了使其正常工作,你的 classpath 上必须有 JMX 实现。
重用现有 MBeanServer
如果未指定服务器,MBeanExporter
会尝试自动检测正在运行的 MBeanServer
。
这在大多数环境中都有效,因为只使用一个 MBeanServer
实例。但是,当存在多个实例时,
导出器可能会选择错误的服务器。在这种情况下,你应该使用 MBeanServer
的 agentId
来指示要使用的实例,如以下示例所示:
<beans>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
<!-- indicate to first look for a server -->
<property name="locateExistingServerIfPossible" value="true"/>
<!-- search for the MBeanServer instance with the given agentId -->
<property name="agentId" value="MBeanServer_instance_agentId>"/>
</bean>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="server" ref="mbeanServer"/>
...
</bean>
</beans>
对于现有 MBeanServer
具有通过查找方法检索的动态(或未知)agentId
的平台或情况,
你应该使用 factory-method,
如以下示例所示:
<beans>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="server">
<!-- Custom MBeanServerLocator -->
<bean class="platform.package.MBeanServerLocator" factory-method="locateMBeanServer"/>
</property>
</bean>
<!-- other beans here -->
</beans>
延迟初始化的 MBean
如果你使用 MBeanExporter
配置了一个 bean,并且该 bean 也配置为延迟初始化,
MBeanExporter
不会破坏此约定,并避免实例化该 bean。相反,它会在 MBeanServer
中注册一个代理,并延迟从容器中获取该 bean,直到代理上发生第一次调用。
这也会影响 FactoryBean
解析,其中 MBeanExporter
会定期自省生成的对象,
从而有效地触发 FactoryBean.getObject()
。为了避免这种情况,请将相应的 bean
定义标记为延迟初始化。
MBean 的自动注册
通过 MBeanExporter
导出的任何已经有效的 MBean 都会原样注册到 MBeanServer
,
无需 Spring 的进一步干预。你可以通过将 autodetect
属性设置为 true
来使 MBeanExporter
自动检测 MBean,如以下示例所示:
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="autodetect" value="true"/>
</bean>
<bean name="spring:mbean=true" class="org.springframework.jmx.export.TestDynamicMBean"/>
在前面的示例中,名为 spring:mbean=true
的 bean 已经是一个有效的 JMX MBean,
并由 Spring 自动注册。默认情况下,为 JMX 注册自动检测的 bean 会将其 bean 名称用作
ObjectName
。你可以覆盖此行为,如 控制你的 Bean 的 ObjectName
实例 中所述。
控制注册行为
考虑这样一种场景:Spring MBeanExporter
尝试使用 ObjectName
bean:name=testBean1
向 MBeanServer
注册一个 MBean
。如果该 ObjectName
下已经注册了一个 MBean
实例,
默认行为是失败(并抛出 InstanceAlreadyExistsException
)。
你可以精确控制 MBean
注册到 MBeanServer
时发生的情况。
Spring 的 JMX 支持允许三种不同的注册行为来控制当注册过程发现 MBean
已在同一 ObjectName
下注册时的注册行为。下表总结了这些注册行为:
注册行为 | 说明 |
---|---|
|
这是默认的注册行为。如果 |
|
如果 |
|
如果 |
上表中的值在 RegistrationPolicy
类上定义为枚举。
如果你想更改默认注册行为,你需要将 MBeanExporter
定义上的
registrationPolicy
属性值设置为其中一个值。
以下示例展示了如何从默认注册行为更改为 REPLACE_EXISTING
行为:
<beans>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="bean:name=testBean1" value-ref="testBean"/>
</map>
</property>
<property name="registrationPolicy" value="REPLACE_EXISTING"/>
</bean>
<bean id="testBean" class="org.springframework.jmx.JmxTestBean">
<property name="name" value="TEST"/>
<property name="age" value="100"/>
</bean>
</beans>