控制 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 必須是公共的,公開操作或屬性的方法也必須是公共的。 |
以下示例顯示了我們用於建立 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 名稱對映到方法名稱列表。