Controlling the Management Interface of Your Beans

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

In the example in the preceding section, you had little control over the management interface of your bean. All of the public properties and methods of each exported bean were exposed as JMX attributes and operations, respectively. To exercise finer-grained control over exactly which properties and methods of your exported beans are actually exposed as JMX attributes and operations, Spring JMX provides a comprehensive and extensible mechanism for controlling the management interfaces of your beans.

Using the MBeanInfoAssembler Interface

在幕后,MBeanExporter 委托给 org.springframework.jmx.export.assembler.MBeanInfoAssembler 接口的实现,该接口负责定义每个公开 Bean 的管理接口。默认实现 org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler 定义了一个管理接口,公开所有公共属性和方法(如您在前几个部分的示例中看到的那样)。Spring 提供了 MBeanInfoAssembler 接口的两个附加实现,使您可以使用源代码级元数据或任何任意接口控制生成的管理接口。

Behind the scenes, the MBeanExporter delegates to an implementation of the org.springframework.jmx.export.assembler.MBeanInfoAssembler interface, which is responsible for defining the management interface of each bean that is exposed. The default implementation, org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler, defines a management interface that exposes all public properties and methods (as you saw in the examples in the preceding sections). Spring provides two additional implementations of the MBeanInfoAssembler interface that let you control the generated management interface by using either source-level metadata or any arbitrary interface.

Using Source-level Metadata: Java Annotations

通过使用 MetadataMBeanInfoAssembler,可以使用源代码级元数据定义 Bean 的管理接口。元数据的读取由 org.springframework.jmx.export.metadata.JmxAttributeSource 接口封装。Spring JMX 提供了一个使用 Java 注解的默认实现,即 org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource。您必须为 MetadataMBeanInfoAssembler 配置 JmxAttributeSource 接口的实现实例才能使其正常运行(没有默认值)。

By using the MetadataMBeanInfoAssembler, you can define the management interfaces for your beans by using source-level metadata. The reading of metadata is encapsulated by the org.springframework.jmx.export.metadata.JmxAttributeSource interface. Spring JMX provides a default implementation that uses Java annotations, namely org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource. You must configure the MetadataMBeanInfoAssembler with an implementation instance of the JmxAttributeSource interface for it to function correctly (there is no default).

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

To mark a bean for export to JMX, you should annotate the bean class with the ManagedResource annotation. You must mark each method you wish to expose as an operation with the ManagedOperation annotation and mark each property you wish to expose with the ManagedAttribute annotation. When marking properties, you can omit either the annotation of the getter or the setter to create a write-only or read-only attribute, respectively.

ManagedResource 注释的 Bean 必须为 public,方法公开一个操作或属性也必须为 public。

A ManagedResource-annotated bean must be public, as must the methods exposing an operation or an attribute.

以下示例显示了我们在 Creating an MBeanServer 中使用的 JmxTestBean 类的注释版本:

The following example shows the annotated version of the JmxTestBean class that we used in Creating an MBeanServer:

import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedAttribute;

@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 implements IJmxTestBean {

	private String name;
	private int age;

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

	public void setAge(int age) {
		this.age = 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 name;
	}

	@ManagedOperation(description="Add two numbers")
	@ManagedOperationParameters({
		@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();
	}

}

在前面的示例中,您可以看到 JmxTestBean 类用 ManagedResource 注释标记,而 ManagedResource 注释使用一组属性进行配置。这些属性可用于配置由 MBeanExporter 生成的 MBean 的各个方面,并在 Source-level Metadata Types 中的后面部分进行了更详细的说明。

In the preceding example, you can see that the JmxTestBean class is marked with the ManagedResource annotation and that this ManagedResource annotation is configured with a set of properties. These properties can be used to configure various aspects of the MBean that is generated by the MBeanExporter and are explained in greater detail later in Source-level Metadata Types.

agename 属性都使用 ManagedAttribute 注解进行了注释,但在 age 属性的情况下,仅标记了 getter。这会导致这两个属性都会作为属性包含在管理接口中,但 age 属性是只读的。

Both the age and name properties are annotated with the ManagedAttribute annotation, but, in the case of the age property, only the getter is marked. This causes both of these properties to be included in the management interface as attributes, but the age attribute is read-only.

最后,add(int, int) 方法用 ManagedOperation 属性标记,而 dontExposeMe() 方法则没有。当使用 MetadataMBeanInfoAssembler 时,这会导致管理接口只包含一项操作 (add(int, int))。

Finally, the add(int, int) method is marked with the ManagedOperation attribute, whereas the dontExposeMe() method is not. This causes the management interface to contain only one operation (add(int, int)) when you use the MetadataMBeanInfoAssembler.

以下配置展示了如何将 MBeanExporter 配置为使用 MetadataMBeanInfoAssembler

The following configuration shows how you can configure the MBeanExporter to use the 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>

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

	<!-- 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="testBean" class="org.springframework.jmx.AnnotationTestBean">
		<property name="name" value="TEST"/>
		<property name="age" value="100"/>
	</bean>
</beans>

在前一个示例中,MetadataMBeanInfoAssembler Bean 使用 AnnotationJmxAttributeSource 类的实例进行配置,然后通过装配器属性传递给 MBeanExporter。只要利用 Spring 暴露 MBean 的元数据驱动管理接口,这就足够了。

In the preceding example, an MetadataMBeanInfoAssembler bean has been configured with an instance of the AnnotationJmxAttributeSource class and passed to the MBeanExporter through the assembler property. This is all that is required to take advantage of metadata-driven management interfaces for your Spring-exposed MBeans.

Source-level Metadata Types

下表描述了适用于 Spring JMX 的源级别元数据类型:

The following table describes the source-level metadata types that are available for use in Spring JMX:

Table 1. Source-level metadata types
Purpose Annotation Annotation Type

Mark all instances of a Class as JMX managed resources.

@ManagedResource

Class

Mark a method as a JMX operation.

@ManagedOperation

Method

Mark a getter or setter as one half of a JMX attribute.

@ManagedAttribute

Method (only getters and setters)

Define descriptions for operation parameters.

@ManagedOperationParameter and @ManagedOperationParameters

Method

下表描述了适用于这些源级别元数据类型的配置参数:

The following table describes the configuration parameters that are available for use on these source-level metadata types:

Table 2. Source-level metadata parameters
Parameter Description Applies to

ObjectName

Used by MetadataNamingStrategy to determine the ObjectName of a managed resource.

ManagedResource

description

Sets the friendly description of the resource, attribute or operation.

ManagedResource, ManagedAttribute, ManagedOperation, or ManagedOperationParameter

currencyTimeLimit

Sets the value of the currencyTimeLimit descriptor field.

ManagedResource or ManagedAttribute

defaultValue

Sets the value of the defaultValue descriptor field.

ManagedAttribute

log

Sets the value of the log descriptor field.

ManagedResource

logFile

Sets the value of the logFile descriptor field.

ManagedResource

persistPolicy

Sets the value of the persistPolicy descriptor field.

ManagedResource

persistPeriod

Sets the value of the persistPeriod descriptor field.

ManagedResource

persistLocation

Sets the value of the persistLocation descriptor field.

ManagedResource

persistName

Sets the value of the persistName descriptor field.

ManagedResource

name

Sets the display name of an operation parameter.

ManagedOperationParameter

index

Sets the index of an operation parameter.

ManagedOperationParameter

Using the AutodetectCapableMBeanInfoAssembler Interface

为了进一步简化配置,Spring 包括 AutodetectCapableMBeanInfoAssembler 接口,该接口扩展了 MBeanInfoAssembler 接口以添加对 MBean 资源自动检测的支持。如果使用 AutodetectCapableMBeanInfoAssembler 实例配置 MBeanExporter,则允许其“投票”将 Bean 包含在暴露于 JMX 内。

To simplify configuration even further, Spring includes the AutodetectCapableMBeanInfoAssembler interface, which extends the MBeanInfoAssembler interface to add support for autodetection of MBean resources. If you configure the MBeanExporter with an instance of AutodetectCapableMBeanInfoAssembler, it is allowed to “vote” on the inclusion of beans for exposure to JMX.

AutodetectCapableMBeanInfo 接口的唯一实现是 MetadataMBeanInfoAssembler,它投票包含任何用 ManagedResource 属性标记的 Bean。本例中的默认方法是将 Bean 名称用作 ObjectName,它生成类似于以下内容的配置:

The only implementation of the AutodetectCapableMBeanInfo interface is the MetadataMBeanInfoAssembler, which votes to include any bean that is marked with the ManagedResource attribute. The default approach in this case is to use the bean name as the ObjectName, which results in a configuration similar to the following:

<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="testBean" class="org.springframework.jmx.JmxTestBean">
		<property name="name" value="TEST"/>
		<property name="age" value="100"/>
	</bean>

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

</beans>

请注意,在前面的配置中,不会将任何 bean 传递给 MBeanExporter。然而,由于 JmxTestBean 已用 ManagedResource 属性标记,并且 MetadataMBeanInfoAssembler 检测到这一点并投票包含它,因此它仍然可以注册。使用此方法的唯一问题在于,JmxTestBean 的名称现在具有业务含义。你可以通过更改 ObjectName 的默认行为(如 Controlling ObjectName Instances for Your Beans 中所定义)来解决此问题。

Notice that, in the preceding configuration, no beans are passed to the MBeanExporter. However, the JmxTestBean is still registered, since it is marked with the ManagedResource attribute and the MetadataMBeanInfoAssembler detects this and votes to include it. The only problem with this approach is that the name of the JmxTestBean now has business meaning. You can address this issue by changing the default behavior for ObjectName creation as defined in Controlling ObjectName Instances for Your Beans.

Defining Management Interfaces by Using Java Interfaces

除了 MetadataMBeanInfoAssembler,Spring 还包括 InterfaceBasedMBeanInfoAssembler,它允许你根据一组接口中定义的方法,限定暴露的方法和属性。

In addition to the MetadataMBeanInfoAssembler, Spring also includes the InterfaceBasedMBeanInfoAssembler, which lets you constrain the methods and properties that are exposed based on the set of methods defined in a collection of interfaces.

尽管公开 MBean 的标准机制是使用接口和简单的命名方案,但 InterfaceBasedMBeanInfoAssembler 通过消除命名惯例的需要、允许你使用超过一个接口以及消除 Bean 实现 MBean 接口的需要,扩展了此功能。

Although the standard mechanism for exposing MBeans is to use interfaces and a simple naming scheme, InterfaceBasedMBeanInfoAssembler extends this functionality by removing the need for naming conventions, letting you use more than one interface and removing the need for your beans to implement the MBean interfaces.

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

Consider the following interface, which is used to define a management interface for the JmxTestBean class that we showed earlier:

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 以将此接口用作管理接口的定义:

This interface defines the methods and properties that are exposed as operations and attributes on the JMX MBean. The following code shows how to configure Spring JMX to use this interface as the definition for the management interface:

<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 管理接口的接口非常重要。

In the preceding example, the InterfaceBasedMBeanInfoAssembler is configured to use the IJmxTestBean interface when constructing the management interface for any bean. It is important to understand that beans processed by the InterfaceBasedMBeanInfoAssembler are not required to implement the interface used to generate the JMX management interface.

在前一个案例中,IJmxTestBean 接口用于构建所有 Bean 的所有管理接口。在许多情况下,这不是所需的行为,你可能希望为不同的 Bean 使用不同的接口。本例中,可以通过 interfaceMappings 属性向 InterfaceBasedMBeanInfoAssembler 传递 Properties 实例,此实例中每个条目的键都是 Bean 名称,每个条目的值都是用于该 Bean 的接口名称的逗号分隔列表。

In the preceding case, the IJmxTestBean interface is used to construct all management interfaces for all beans. In many cases, this is not the desired behavior, and you may want to use different interfaces for different beans. In this case, you can pass InterfaceBasedMBeanInfoAssembler a Properties instance through the interfaceMappings property, where the key of each entry is the bean name and the value of each entry is a comma-separated list of interface names to use for that bean.

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

If no management interface is specified through either the managedInterfaces or interfaceMappings properties, the InterfaceBasedMBeanInfoAssembler reflects on the bean and uses all of the interfaces implemented by that bean to create the management interface.

Using MethodNameBasedMBeanInfoAssembler

MethodNameBasedMBeanInfoAssembler 允许你指定一个方法列表,该列表用作 JMX 中的属性和操作。以下代码展示了示例配置:

MethodNameBasedMBeanInfoAssembler lets you specify a list of method names that are exposed to JMX as attributes and operations. The following code shows a sample configuration:

<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 名称映射到方法名称的列表。

In the preceding example, you can see that the add and myOperation methods are exposed as JMX operations, and getName(), setName(String), and getAge() are exposed as the appropriate half of a JMX attribute. In the preceding code, the method mappings apply to beans that are exposed to JMX. To control method exposure on a bean-by-bean basis, you can use the methodMappings property of MethodNameMBeanInfoAssembler to map bean names to lists of method names.