控制您的 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
。您必須為 MetadataMBeanInfoAssembler
配置一個 JmxAttributeSource
介面的實現例項才能使其正常工作,因為沒有預設實現。
要標記一個 bean 以匯出到 JMX,您應該使用 @ManagedResource
註解標註 bean 類。您必須使用 @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
時,這使得管理介面只包含一個操作(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 中使用的註解
註解 | 應用於 | 描述 |
---|---|---|
|
類 |
將 |
|
類 |
指示由受管資源發出的 JMX 通知。 |
|
方法(僅 getter 和 setter) |
將 getter 或 setter 標記為 JMX 屬性的一部分。 |
|
方法(僅 getter) |
將 getter 標記為 JMX 屬性,並新增描述符屬性以指示它是度量。 |
|
方法 |
將方法標記為 JMX 操作。 |
|
方法 |
定義操作引數的描述。 |
下表描述了這些註解中可用的一些常用屬性。有關更多詳細資訊,請查閱每個註解的 Javadoc。
屬性 | 應用於 | 描述 |
---|---|---|
|
|
由 |
|
|
設定資源、通知、屬性、度量或操作的描述。 |
|
|
設定 |
|
|
設定 |
|
|
設定 |
|
|
設定 |
|
|
設定 |
|
|
設定 |
|
|
設定 |
|
|
設定 |
|
|
設定操作引數的顯示名稱。 |
|
|
設定操作引數的索引。 |
使用 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 的介面名稱的逗號分隔列表。
如果透過 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 名稱對映到方法名稱列表。