Exporting Your Beans to 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
。你可以更改此行为,如 Controlling ObjectName
Instances for Your Beans 中所述。
通过此配置,testBean
bean 被公开为 ObjectName
bean:name=testBean1
下的一个 MBean。默认情况下,bean 的所有 public
属性都公开为属性,所有 public
方法(除从 Object
类继承的方法外)都公开为操作。
|
Creating an MBeanServer
preceding section 中显示的配置假定应用程序在已经运行一个(且只有一个)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
实例。为了正确执行此操作,您的类路径中必须具有 JMX 实施。
Reusing an Existing 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>
Lazily Initialized MBeans
如果您使用也已配置为延迟初始化的 MBeanExporter
配置一个 bean,则 MBeanExporter
不会打破此契约,并避免实例化该 bean。取而代之的是,它会使用 MBeanServer
注册一个代理,并推迟从容器中获取 bean,直至对该代理的首次调用发生。
这也影响 FactoryBean
解析,因为 MBeanExporter
会定期反省生成的对象,从而有效触发 FactoryBean.getObject()
。为了避免这种情况,请将相应的 bean 定义标记为延迟初始化。
Automatic Registration of MBeans
任何通过 MBeanExporter
导出且已经有效的 MBean 会在没有 Spring 进一步干预的情况下按原样注册到 MBeanServer
。您可以通过将 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`。你可以覆盖此行为,如Controlling ObjectName
Instances for Your Beans中所述。
Controlling the Registration Behavior
考虑 Spring MBeanExporter
尝试通过使用 ObjectName
bean:name=testBean1
向 MBeanServer
注册 MBean
的场景。如果 MBean
实例已在该相同 ObjectName
下注册,则默认行为是失败(并抛出 InstanceAlreadyExistsException
)。
您可以精确控制将 MBean
注册到 MBeanServer
时的操作。Spring 的 JMX 支持允许三种不同的注册行为来控制查找进程发现某个 MBean
已在相同 ObjectName
下注册时的注册行为。下表总结了这些注册行为:
Registration behavior | Explanation |
---|---|
|
这是默认的注册行为。如果一个 |
|
如果一个 |
|
如果一个 |
前表中的值定义为 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>