Bean の管理インターフェースの制御

前のセクションの例では、Bean の管理インターフェースをほとんど制御できませんでした。エクスポートされた各 Bean のすべての public プロパティとメソッドは、それぞれ JMX 属性と操作として公開されました。エクスポートされた Bean のどのプロパティとメソッドが実際に JMX 属性および操作として公開されるかを正確に細かく制御するために、Spring JMX は Bean の管理インターフェースを制御するための包括的で拡張可能なメカニズムを提供します。

MBeanInfoAssembler API の使用

バックグラウンドでは、MBeanExporter は、公開される各 Bean の管理インターフェースの定義を担当する org.springframework.jmx.export.assembler.MBeanInfoAssembler API の実装に委譲します。デフォルトの実装である org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler は、すべてのパブリックプロパティとメソッドを公開する管理インターフェースを定義します (前のセクションの例で確認したとおり)。Spring は、ソースレベルのメタデータまたは任意のインターフェースを使用して、生成された管理インターフェースを制御できる MBeanInfoAssembler インターフェースの 2 つの追加実装を提供します。

ソースレベルのメタデータの使用: Java アノテーション

MetadataMBeanInfoAssembler を使用すると、ソースレベルのメタデータを使用して Bean の管理インターフェースを定義できます。メタデータの読み取りは、org.springframework.jmx.export.metadata.JmxAttributeSource インターフェースによってカプセル化されます。Spring JMX は、Java アノテーションを使用するデフォルトの実装、つまり org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource を提供します。デフォルトがないため、正しく機能させるには、JmxAttributeSource インターフェースの実装インスタンスを使用して MetadataMBeanInfoAssembler を構成する必要があります。

Bean を JMX にエクスポートするためにマークするには、Bean クラスに @ManagedResource アノテーションを付ける必要があります。操作として公開する各メソッドに @ManagedOperation アノテーションを付け、公開する各プロパティに @ManagedAttribute アノテーションを付ける必要があります。プロパティにアノテーションを付けるときに、getter または setter のアノテーションを省略して、それぞれ書き込み専用または読み取り専用の属性を作成できます。

@ManagedResource でアノテーションが付けられた Bean は、操作または属性を公開するメソッドと同様に、パブリックである必要があります。

次の例は、MBeanServer の作成で使用した JmxTestBean クラスのアノテーション付きバージョンを示しています。

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 アノテーションで説明します。

age プロパティと name プロパティの両方に @ManagedAttribute のアノテーションが付けられていますが、age プロパティの場合は、getter メソッドのみがアノテーション付けされています。これにより、これらのプロパティは両方とも管理対象属性として管理インターフェースに含まれますが、age 属性は読み取り専用になります。

最後に、add(int, int) メソッドには @ManagedOperation のアノテーションが付けられていますが、dontExposeMe() メソッドには付けられていません。これにより、MetadataMBeanInfoAssembler を使用する場合、管理インターフェースには 1 つの操作 (add(int, int)) のみが含まれることになります。

JMX 管理インターフェースはアノテーションからのみ派生されるため、AnnotationTestBean クラスは Java インターフェースを実装する必要はありません。

次の構成は、MetadataMBeanInfoAssembler を使用するように MBeanExporter を構成する方法を示しています。

<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 クラスのインスタンスで構成され、アセンブラプロパティを介して 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

マネージリソースの ObjectName を決定するために MetadataNamingStrategy によって使用されます。

description

@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 を構成すると、JMX に公開する Bean の組み込みについて「投票」できるようになります。

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>

上記の構成では、MBeanExporter に Bean が渡されていないことに注意してください。ただし、AnnotationTestBean は @ManagedResource でアノテーションが付けられており、MetadataMBeanInfoAssembler がこれを検出して含めるように投票するため、登録されたままです。このアプローチの唯一の欠点は、AnnotationTestBean の名前にビジネス上の意味が加わることです。この課題は、Bean の ObjectName インスタンスの制御に従って、ObjectNamingStrategy を構成することで対処できます。ソースレベルのメタデータの使用: 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 ごとに異なるインターフェースを使用することをお勧めします。この場合、InterfaceBasedMBeanInfoAssembler に interfaceMappings プロパティを介して Properties インスタンスを渡すことができます。各エントリのキーは Bean 名で、各エントリの値はその Bean に使用するインターフェース名のコンマ区切りリストです。

managedInterfaces または interfaceMappings プロパティのいずれかで管理インターフェースが指定されていない場合、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>

前の例では、add メソッドと myOperation メソッドが JMX 操作として公開され、getName()setName(String)getAge() が JMX 属性の適切な半分として公開されていることがわかります。上記のコードでは、メソッドマッピングは JMX に公開されている Bean に適用されます。Bean ごとにメソッドの公開を制御するには、MethodNameMBeanInfoAssembler の methodMappings プロパティを使用して、Bean 名をメソッド名のリストにマップできます。