控制 Bean 的管理接口

前一节的示例中,您对 bean 的管理接口几乎没有控制权。每个导出的 bean 的所有 public 属性和方法都分别作为 JMX 属性和操作公开。为了对导出 bean 的哪些属性和方法实际上作为 JMX 属性和操作公开进行更细粒度的控制,Spring JMX 提供了一个全面且可扩展的机制来控制您的 bean 的管理接口。

使用 MBeanInfoAssembler API

在幕后,MBeanExporter 将委托给 org.springframework.jmx.export.assembler.MBeanInfoAssembler API 的实现,该实现负责定义每个公开的 bean 的管理接口。默认实现 org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler 定义了一个管理接口,该接口公开所有公共属性和方法(如您在前面几节的示例中所见)。Spring 提供了 MBeanInfoAssembler 接口的两个额外实现,允许您通过使用源级元数据或任何任意接口来控制生成的管理接口。

使用源级元数据:Java 注解

通过使用 MetadataMBeanInfoAssembler,您可以使用源级元数据为您的 bean 定义管理接口。元数据的读取由 org.springframework.jmx.export.metadata.JmxAttributeSource 接口封装。Spring JMX 提供了一个使用 Java 注解的默认实现,即 org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource。您必须使用 JmxAttributeSource 接口的实现实例配置 MetadataMBeanInfoAssembler,以便它正常工作,因为没有默认值。

要将 bean 标记为导出到 JMX,您应该使用 @ManagedResource 注解注释 bean 类。您必须使用 @ManagedOperation 注解注释您希望作为操作公开的每个方法,并使用 @ManagedAttribute 注解注释您希望公开的每个属性。在注释属性时,您可以省略 getter 或 setter 的注释以分别创建只写或只读属性。

@ManagedResource 注解的 bean 必须是公共的,公开操作或属性的方法也必须是公共的。

以下示例显示了我们用于创建 MBeanServerJmxTestBean 类的注释版本。

package org.springframework.jmx;

@ManagedResource(
		objectName="bean:name=testBean4",
		description="My Managed Bean",
		log=true,
		logFile="jmx.log",
		currencyTimeLimit=15,
		persistPolicy="OnUpdate",
		persistPeriod=200,
		persistLocation="foo",
		persistName="bar")
public class AnnotationTestBean {

	private int age;
	private String name;

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

	@ManagedAttribute(description="The Age Attribute", currencyTimeLimit=15)
	public int getAge() {
		return this.age;
	}

	@ManagedAttribute(description="The Name Attribute",
			currencyTimeLimit=20,
			defaultValue="bar",
			persistPolicy="OnUpdate")
	public void setName(String name) {
		this.name = name;
	}

	@ManagedAttribute(defaultValue="foo", persistPeriod=300)
	public String getName() {
		return this.name;
	}

	@ManagedOperation(description="Add two numbers")
	@ManagedOperationParameter(name = "x", description = "The first number")
	@ManagedOperationParameter(name = "y", description = "The second number")
	public int add(int x, int y) {
		return x + y;
	}

	public void dontExposeMe() {
		throw new RuntimeException();
	}

}

在前面的示例中,您可以看到 AnnotationTestBean 类已用 @ManagedResource 注解,并且此 @ManagedResource 注解已配置了一组属性。这些属性可用于配置 MBeanExporter 生成的 MBean 的各个方面,并将在后面的Spring JMX 注解中详细解释。

agename 属性都已用 @ManagedAttribute 注解,但在 age 属性的情况下,只有 getter 方法已注释。这使得这两个属性都作为托管属性包含在管理接口中,但 age 属性是只读的。

最后,add(int, int) 方法已用 @ManagedOperation 注解,而 dontExposeMe() 方法没有。当您使用 MetadataMBeanInfoAssembler 时,这会导致管理接口仅包含一个操作 (add(int, int))。

AnnotationTestBean 类不需要实现任何 Java 接口,因为 JMX 管理接口完全来自注解。

以下配置显示了如何配置 MBeanExporter 以使用 MetadataMBeanInfoAssembler

<beans>

	<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
		<property name="assembler" ref="assembler"/>
		<property name="namingStrategy" ref="namingStrategy"/>
		<property name="autodetect" value="true"/>
	</bean>

	<!-- will create management interface using annotation metadata -->
	<bean id="assembler"
			class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
		<property name="attributeSource" ref="jmxAttributeSource"/>
	</bean>

	<!-- will pick up the ObjectName from the annotation -->
	<bean id="namingStrategy"
			class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
		<property name="attributeSource" ref="jmxAttributeSource"/>
	</bean>

	<bean id="jmxAttributeSource"
			class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>

	<bean id="testBean" class="org.springframework.jmx.AnnotationTestBean">
		<property name="name" value="TEST"/>
		<property name="age" value="100"/>
	</bean>

</beans>

在前面的示例中,MetadataMBeanInfoAssembler bean 已配置了 AnnotationJmxAttributeSource 类的实例,并通过 assembler 属性传递给 MBeanExporter。这就是利用 Spring 公开的 MBean 的注解驱动管理接口所需的一切。

Spring JMX 注解

下表描述了 Spring JMX 中可用的注解

表 1. Spring JMX 注解
注解 适用于 描述

@ManagedResource

Class 的所有实例标记为 JMX 托管资源。

@ManagedNotification

指示托管资源发出的 JMX 通知。

@ManagedAttribute

方法(仅限 getter 和 setter)

将 getter 或 setter 标记为 JMX 属性的一半。

@ManagedMetric

方法(仅限 getter)

将 getter 标记为 JMX 属性,并添加描述符属性以指示它是一个指标。

@ManagedOperation

方法

将方法标记为 JMX 操作。

@ManagedOperationParameter

方法

为操作参数定义描述。

下表描述了这些注解中可用的一些常用属性。有关详细信息,请查阅每个注解的 Javadoc。

表 2. Spring JMX 注解属性
属性 适用于 描述

objectName

@ManagedResource

MetadataNamingStrategy 用于确定托管资源的 ObjectName

描述

@ManagedResource@ManagedNotification@ManagedAttribute@ManagedMetric@ManagedOperation@ManagedOperationParameter

设置资源、通知、属性、指标或操作的描述。

currencyTimeLimit

@ManagedResource@ManagedAttribute@ManagedMetric

设置 currencyTimeLimit 描述符字段的值。

defaultValue

@ManagedAttribute

设置 defaultValue 描述符字段的值。

log

@ManagedResource

设置 log 描述符字段的值。

logFile

@ManagedResource

设置 logFile 描述符字段的值。

persistPolicy

@ManagedResource@ManagedMetric

设置 persistPolicy 描述符字段的值。

persistPeriod

@ManagedResource@ManagedMetric

设置 persistPeriod 描述符字段的值。

persistLocation

@ManagedResource

设置 persistLocation 描述符字段的值。

persistName

@ManagedResource

设置 persistName 描述符字段的值。

name

@ManagedOperationParameter

设置操作参数的显示名称。

index

@ManagedOperationParameter

设置操作参数的索引。

使用 AutodetectCapableMBeanInfoAssembler 接口

为了进一步简化配置,Spring 包含了 AutodetectCapableMBeanInfoAssembler 接口,该接口扩展了 MBeanInfoAssembler 接口,以添加对 MBean 资源自动检测的支持。如果您使用 AutodetectCapableMBeanInfoAssembler 的实例配置 MBeanExporter,则允许它“投票”决定是否将 bean 公开给 JMX。

AutodetectCapableMBeanInfo 接口的唯一实现是 MetadataMBeanInfoAssembler,它投票决定包含任何标记有 ManagedResource 属性的 bean。在这种情况下,默认方法是使用 bean 名称作为 ObjectName,这会导致类似于以下内容的配置

<beans>

	<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
		<!-- notice how no 'beans' are explicitly configured here -->
		<property name="autodetect" value="true"/>
		<property name="assembler" ref="assembler"/>
	</bean>

	<bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
		<property name="attributeSource">
			<bean class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
		</property>
	</bean>

	<bean id="testBean" class="org.springframework.jmx.AnnotationTestBean">
		<property name="name" value="TEST"/>
		<property name="age" value="100"/>
	</bean>

</beans>

请注意,在前面的配置中,没有将 bean 传递给 MBeanExporter。但是,AnnotationTestBean 仍然被注册,因为它已用 @ManagedResource 注解,并且 MetadataMBeanInfoAssembler 检测到此并投票决定包含它。这种方法的唯一缺点是 AnnotationTestBean 的名称现在具有业务意义。您可以通过配置 ObjectNamingStrategy 来解决此问题,如控制您的 Bean 的 ObjectName 实例中所述。您还可以在使用源级元数据:Java 注解中看到一个使用 MetadataNamingStrategy 的示例。

使用 Java 接口定义管理接口

除了 MetadataMBeanInfoAssembler,Spring 还包括 InterfaceBasedMBeanInfoAssembler,它允许您根据接口集合中定义的方法集来限制公开的方法和属性。

尽管公开 MBean 的标准机制是使用接口和简单的命名方案,但 InterfaceBasedMBeanInfoAssembler 通过消除对命名约定的需求、允许您使用多个接口以及消除您的 bean 实现 MBean 接口的需求来扩展此功能。

考虑以下接口,它用于为我们之前展示的 JmxTestBean 类定义管理接口

public interface IJmxTestBean {

	public int add(int x, int y);

	public long myOperation();

	public int getAge();

	public void setAge(int age);

	public void setName(String name);

	public String getName();

}

此接口定义了作为 JMX MBean 上的操作和属性公开的方法和属性。以下代码显示了如何配置 Spring JMX 以使用此接口作为管理接口的定义

<beans>

	<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
		<property name="beans">
			<map>
				<entry key="bean:name=testBean5" value-ref="testBean"/>
			</map>
		</property>
		<property name="assembler">
			<bean class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
				<property name="managedInterfaces">
					<value>org.springframework.jmx.IJmxTestBean</value>
				</property>
			</bean>
		</property>
	</bean>

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

</beans>

在前面的示例中,InterfaceBasedMBeanInfoAssembler 配置为在为任何 bean 构造管理接口时使用 IJmxTestBean 接口。重要的是要理解,由 InterfaceBasedMBeanInfoAssembler 处理的 bean 不需要实现用于生成 JMX 管理接口的接口。

在前面的情况下,IJmxTestBean 接口用于为所有 bean 构造所有管理接口。在许多情况下,这并不是期望的行为,您可能希望为不同的 bean 使用不同的接口。在这种情况下,您可以通过 interfaceMappings 属性将 Properties 实例传递给 InterfaceBasedMBeanInfoAssembler,其中每个条目的键是 bean 名称,每个条目的值是用于该 bean 的逗号分隔的接口名称列表。

如果通过 managedInterfacesinterfaceMappings 属性未指定管理接口,则 InterfaceBasedMBeanInfoAssembler 会反映 bean 并使用该 bean 实现的所有接口来创建管理接口。

使用 MethodNameBasedMBeanInfoAssembler

MethodNameBasedMBeanInfoAssembler 允许您指定要公开给 JMX 作为属性和操作的方法名称列表。以下代码显示了一个示例配置

<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
	<property name="beans">
		<map>
			<entry key="bean:name=testBean5" value-ref="testBean"/>
		</map>
	</property>
	<property name="assembler">
		<bean class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler">
			<property name="managedMethods">
				<value>add,myOperation,getName,setName,getAge</value>
			</property>
		</bean>
	</property>
</bean>

在前面的示例中,您可以看到 addmyOperation 方法作为 JMX 操作公开,而 getName()setName(String)getAge() 作为 JMX 属性的相应部分公开。在前面的代码中,方法映射适用于公开给 JMX 的 bean。为了在逐个 bean 的基础上控制方法公开,您可以使用 MethodNameMBeanInfoAssemblermethodMappings 属性将 bean 名称映射到方法名称列表。

© . This site is unofficial and not affiliated with VMware.