控制 Bean 的管理介面
在前一節的範例中,您對 Bean 的管理介面幾乎沒有控制權。每個匯出 Bean 的所有 public
屬性和方法都會分別公開為 JMX 屬性和操作。為了更精細地控制哪些匯出 Bean 的屬性和方法實際公開為 JMX 屬性和操作,Spring JMX 提供了一個全面且可擴充的機制來控制 Bean 的管理介面。
使用 MBeanInfoAssembler
API
在幕後,MBeanExporter
委派給 org.springframework.jmx.export.assembler.MBeanInfoAssembler
API 的實作,該 API 負責定義每個公開 Bean 的管理介面。預設實作 org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler
定義了一個管理介面,該介面公開所有 public 屬性和方法(如您在前幾節的範例中所見)。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 必須是 public,公開操作或屬性的方法也必須是 public。 |
以下範例顯示了我們在建立 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>
在前面的範例中,已使用 AnnotationJmxAttributeSource
類別的實例組態了 MetadataMBeanInfoAssembler
Bean,並透過 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 名稱對應到方法名稱清單。