此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10spring-doc.cadn.net.cn

将 Bean 导出到 JMX

Spring 的 JMX 框架中的核心类是MBeanExporter.这个类是 负责获取您的 Spring Bean 并将它们注册到 JMXMBeanServer. 例如,考虑以下类:spring-doc.cadn.net.cn

public class JmxTestBean implements IJmxTestBean {

	private String name;
	private int age;

	@Override
	public int getAge() {
		return age;
	}

	@Override
	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public int add(int x, int y) {
		return x + y;
	}

	@Override
	public void dontExposeMe() {
		throw new RuntimeException();
	}
}
class JmxTestBean : IJmxTestBean {

	override lateinit var name: String
	override var age = 0

	override fun add(x: Int, y: Int): Int {
		return x + y
	}

	override fun dontExposeMe() {
		throw RuntimeException()
	}
}

将此 bean 的属性和方法公开为 MBean,您可以配置MBeanExporter您的 配置文件并传入 bean,如以下示例所示:spring-doc.cadn.net.cn

@Configuration
public class JmxConfiguration {

	@Bean
	MBeanExporter exporter(JmxTestBean testBean) {
		MBeanExporter exporter = new MBeanExporter();
		exporter.setBeans(Map.of("bean:name=testBean1", testBean));
		return exporter;
	}

	@Bean
	JmxTestBean testBean() {
		JmxTestBean testBean = new JmxTestBean();
		testBean.setName("TEST");
		testBean.setAge(100);
		return testBean;
	}
}
@Configuration
class JmxConfiguration {

	@Bean
	fun exporter(testBean: JmxTestBean) = MBeanExporter().apply {
		setBeans(mapOf("bean:name=testBean1" to testBean))
	}

	@Bean
	fun testBean() = JmxTestBean().apply {
		name = "TEST"
		age = 100
	}
}
<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
	   https://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- this bean must not be lazily initialized if the exporting is to happen -->
	<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
		<property name="beans">
			<map>
				<entry key="bean:name=testBean1" value-ref="testBean"/>
			</map>
		</property>
	</bean>

	<bean id="testBean" class="org.example.JmxTestBean">
		<property name="name" value="TEST"/>
		<property name="age" value="100"/>
	</bean>
</beans>

前面配置代码段中的相关 bean 定义是exporter豆。这beans属性告诉MBeanExporter究竟你的豆子必须是哪一个 导出到 JMXMBeanServer.在默认配置中,每个条目的键 在beans Map用作ObjectName对于 相应的条目值。您可以更改此行为,如控制ObjectNameBean 的实例.spring-doc.cadn.net.cn

使用此配置,testBeanbean 在ObjectName bean:name=testBean1.默认情况下,所有public豆子的属性 作为属性公开,并且所有public方法(除了那些继承自Object类)作为作公开。spring-doc.cadn.net.cn

MBeanExporter是一个Lifecyclebean(参见启动和关闭回调)。默认情况下,MBean 在 应用程序生命周期。您可以配置phase在其中 导出发生或通过设置autoStartup旗。

创建 MBeanServer

上一节中显示的配置假定 应用程序在具有一个(并且只有一个)的环境中运行MBeanServer已经运行。在这种情况下,Spring 会尝试找到正在运行的MBeanServer和 向该服务器(如果有)注册您的 Bean。当您的 应用程序在容器(例如 Tomcat 或 IBM WebSphere)中运行,该容器具有其 有MBeanServer.spring-doc.cadn.net.cn

但是,这种方法在独立环境中或在内部运行时没有用处 不提供MBeanServer.要解决此问题,您可以创建一个MBeanServer实例,通过添加org.springframework.jmx.support.MBeanServerFactoryBeanclass 添加到您的配置中。 您还可以确保特定的MBeanServer通过设置MBeanExporter实例的server属性设置为MBeanServer返回的值MBeanServerFactoryBean,如以下示例所示:spring-doc.cadn.net.cn

<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>

在前面的示例中,实例MBeanServerMBeanServerFactoryBean并且是 提供给MBeanExporter通过server财产。当您提供自己的MBeanServer实例,MBeanExporter不尝试定位正在运行的MBeanServer并使用提供的MBeanServer实例。为此,要发挥作用 正确地,您的类路径上必须有一个 JMX 实现。spring-doc.cadn.net.cn

重用现有的MBeanServer

如果未指定服务器,则MBeanExporter尝试自动检测正在运行的MBeanServer.这适用于大多数环境中,其中只有一个MBeanServer实例是 使用。但是,当存在多个实例时,导出器可能会选择错误的服务器。 在这种情况下,您应该使用MBeanServer agentId以指示要使用的实例 使用,如以下示例所示:spring-doc.cadn.net.cn

<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, 如以下示例所示:spring-doc.cadn.net.cn

<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

如果将 Bean 配置为MBeanExporter也配置为 lazy 初始化,则MBeanExporter不违约,避免 实例化 bean。相反,它使用MBeanServer并推迟 从容器中获取 Bean,直到对代理进行第一次调用。spring-doc.cadn.net.cn

这也会影响FactoryBeanresolution,其中MBeanExporter会定期 对产生的对象进行内省,有效触发FactoryBean.getObject(). 为了避免这种情况,请将相应的 bean 定义标记为 lazy-init。spring-doc.cadn.net.cn

自动注册 MBean

通过MBeanExporter并且已经是有效的 MBean 按原样注册到MBeanServer没有斯普林的进一步干预。 您可以使 MBean 由MBeanExporter通过设置 这autodetect属性设置为true,如以下示例所示:spring-doc.cadn.net.cn

<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已经是一个有效的 JMX MBean 并由 Spring 自动注册。默认情况下,自动检测 JMX 的 Bean 注册的 bean 名称用作ObjectName.您可以覆盖此行为, 详见控制ObjectNameBean 的实例.spring-doc.cadn.net.cn

控制注册行为

考虑以下场景: 弹簧MBeanExporter尝试注册MBean使用MBeanServer通过使用ObjectName bean:name=testBean1.如果MBean实例已在同一个ObjectName,默认行为 是失败(并抛出一个InstanceAlreadyExistsException).spring-doc.cadn.net.cn

您可以精确控制当MBean是 注册MBeanServer.Spring 的 JMX 支持允许三种不同的 注册行为,以控制注册时的注册行为 进程发现MBean已在同一ObjectName. 下表总结了这些注册行为:spring-doc.cadn.net.cn

表 1.注册行为
注册行为 解释

FAIL_ON_EXISTINGspring-doc.cadn.net.cn

这是默认注册行为。如果MBean实例已经被 在相同下注册ObjectNameMBean正在注册的不是 registered,以及InstanceAlreadyExistsException被抛出。现有的MBean不受影响。spring-doc.cadn.net.cn

IGNORE_EXISTINGspring-doc.cadn.net.cn

如果MBean实例已在同一ObjectNameMBean正在注册的未注册。现有的MBean是 不受影响,并且没有Exception被抛出。这在以下设置中很有用: 多个应用程序希望共享一个公共的MBean在共享的MBeanServer.spring-doc.cadn.net.cn

REPLACE_EXISTINGspring-doc.cadn.net.cn

如果MBean实例已在同一ObjectName这 现存MBean之前注册的 是未注册的,而新的MBean在其位置注册(新的MBean有效地取代了 前一个实例)。spring-doc.cadn.net.cn

上表中的值定义为RegistrationPolicy类。 如果要更改默认注册行为,需要将registrationPolicy您的财产MBeanExporter定义到其中之一 值。spring-doc.cadn.net.cn

以下示例演示如何从默认注册更改 行为设置为REPLACE_EXISTING行为:spring-doc.cadn.net.cn

<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>