Bean を JMX にエクスポートする
Spring の JMX フレームワークのコアクラスは MBeanExporter
です。このクラスは、Spring Bean を取得し、JMX MBeanServer
に登録します。例: 次のクラスを検討します。
package org.springframework.jmx;
public class JmxTestBean implements IJmxTestBean {
private String name;
private int age;
private boolean isSuperman;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int add(int x, int y) {
return x + y;
}
public void dontExposeMe() {
throw new RuntimeException();
}
}
この Bean のプロパティとメソッドを MBean の属性と操作として公開するには、次の例に示すように、構成ファイルで MBeanExporter
クラスのインスタンスを構成し、Bean を渡すことができます。
<beans>
<!-- this bean must not be lazily initialized if the exporting is to happen -->
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="beans">
<map>
<entry key="bean:name=testBean1" value-ref="testBean"/>
</map>
</property>
</bean>
<bean id="testBean" class="org.springframework.jmx.JmxTestBean">
<property name="name" value="TEST"/>
<property name="age" value="100"/>
</bean>
</beans>
上記の構成スニペットからの適切な Bean 定義は、exporter
Bean です。beans
プロパティは、どの Bean を JMX MBeanServer
にエクスポートする必要があるかを MBeanExporter
に正確に伝えます。デフォルト構成では、beans
Map
の各エントリのキーは、対応するエントリ値によって参照される Bean の ObjectName
として使用されます。Bean の ObjectName
インスタンスの制御に従って、この動作を変更できます。
この構成では、testBean
Bean は ObjectName
bean:name=testBean1
で MBean として公開されます。デフォルトでは、Bean のすべての public
プロパティは属性として公開され、すべての public
メソッド(Object
クラスから継承されたものを除く)は操作として公開されます。
MBeanExporter は Lifecycle Bean です(起動とシャットダウンのコールバックを参照)。デフォルトでは、MBean はアプリケーションのライフサイクル中にできるだけ遅くエクスポートされます。autoStartup フラグを設定することにより、エクスポートが行われる phase を構成したり、自動登録を無効にしたりできます。 |
MBeanServer の作成
前のセクションに示されている構成は、1 つ(および 1 つ)の 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>
上記の例では、MBeanServer
のインスタンスが MBeanServerFactoryBean
によって作成され、server
プロパティを介して MBeanExporter
に提供されます。独自の MBeanServer
インスタンスを提供する場合、MBeanExporter
は実行中の MBeanServer
を見つけようとせず、提供された MBeanServer
インスタンスを使用します。これが正しく機能するには、クラスパスに JMX 実装が必要です。
既存の MBeanServer
の再利用
サーバーが指定されていない場合、MBeanExporter
は実行中の MBeanServer
を自動的に検出しようとします。これは、MBeanServer
インスタンスが 1 つだけ使用されるほとんどの環境で機能します。ただし、複数のインスタンスが存在する場合、エクスポータは間違ったサーバーを選択する可能性があります。このような場合、次の例に示すように、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>
遅延初期化された MBean
遅延初期化用に構成された MBeanExporter
を使用して Bean を構成する場合、MBeanExporter
はこの契約を破らず、Bean のインスタンス化を回避します。代わりに、プロキシを MBeanServer
に登録し、プロキシで最初の呼び出しが発生するまでコンテナーから Bean の取得を延期します。
これは、MBeanExporter
が生成されたオブジェクトを定期的にイントロスペクトし、効果的に FactoryBean.getObject()
をトリガーする FactoryBean
解決にも影響します。これを回避するには、対応する Bean 定義を Lazy-init としてマークします。
MBean の自動登録
MBeanExporter
を介してエクスポートされ、すでに有効な MBean である Bean は、Spring からの介入なしに MBeanServer
にそのまま登録されます。次の例に示すように、autodetect
プロパティを true
に設定することにより、MBean を MBeanExporter
によって自動的に検出させることができます。
<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
として使用されます。Bean の ObjectName
インスタンスの制御で詳述されているように、この動作をオーバーライドできます。
登録動作の制御
Spring MBeanExporter
が ObjectName
bean:name=testBean1
を使用して MBean
を MBeanServer
に登録しようとするシナリオを考えてみます。MBean
インスタンスが同じ ObjectName
ですでに登録されている場合、デフォルトの動作は失敗します(そして InstanceAlreadyExistsException
をスローします)。
MBean
が MBeanServer
に登録されたときに何が起こるかを正確に制御できます。Spring の JMX サポートでは、MBean
が同じ ObjectName
にすでに登録されていることが登録プロセスで検出された場合、3 つの異なる登録動作により登録動作を制御できます。次の表は、これらの登録動作をまとめたものです。
登録動作 | 説明 |
---|---|
| これがデフォルトの登録動作です。 |
|
|
|
|
上記の表の値は、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>