?
This document uses PHP Chinese website manual Release
在前面的例子里,對于你的Bean,你幾乎沒有什么控制權(quán)。每個輸出Bean的所有的 public 屬性和方法都被暴露成了相應(yīng)的JMX的屬性和操作。要對Bean的確切哪個屬性和方法暴露成JMX的屬性和操作實施細粒度的控制,Spring JMX提供了一套全面的以及可擴展的機制來控制bean的管理接口。
MBeanExporter
在后臺委托給了負責定義bean管理接口的
org.springframework.jmx.export.assembler.MBeanInfoAssembler
的一個實現(xiàn)來管理暴露Bean的信息。缺省實現(xiàn)是 org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler
,它僅定義了一個暴露所有public屬性,public方法的管理接口(像你在前面例子看到的那樣)。
Spring還提供了兩個 MBeanInfoAssembler
接口的實現(xiàn),
使你可以使用源碼級元數(shù)據(jù)或者其他任意接口來控制管理接口的產(chǎn)生。
使用 MetadataMBeanInfoAssembler
,你能夠用源碼級元數(shù)據(jù)給你的Bean定義管理接口。
org.springframework.jmx.export.metadata.JmxAttributeSource
封裝了元數(shù)據(jù)的讀取。
Sprin的JMX支持提供了這個接口的兩個現(xiàn)成的實現(xiàn)。對應(yīng)Commons Attributes是 org.springframework.jmx.export.metadata.AttributesJmxAttributeSource
,
而對應(yīng)于JDK 5.0注解的是 org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource
。
為了使 MetadataMBeanInfoAssembler
正確運作,(由于沒有缺省的配置實例)。
我們必須給它配置一個 JmxAttributeSource
接口的實例。下面例子中,我們將采取Commons Attributes的方法。
要標識一個Bean輸出到JMX,你應(yīng)該用 ManagedResource
屬性注解那個Bean的類。
使用Commons Attributes元數(shù)據(jù)的這種方法的情況下,我們可以在 org.springframework.jmx.metadata
包里找到它。
每個你想要暴露為操作的方法,每個你想要暴露的屬性,你都要將用 ManagedOperation
屬性標識它。
當標識屬性的時,為了產(chǎn)生只寫或者只讀的屬性,你可以忽略注解對應(yīng)的getter或者setter方法。
下面例子中,我們用Commons Attributes元數(shù)據(jù)標識了在前面例子看到的 JmxTestBean
類。
package org.springframework.jmx; public class JmxTestBean implements IJmxTestBean { private String name; private int age; 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(); } }
你看到 JmxTestBean
被 ManagedResource
屬性標識了,且 ManagedResource
又配置了一堆的屬性。
這些屬性用來配置由 MBeanExporter
是產(chǎn)生的MBean的方方面面。
第?20.3.4?節(jié) “源代碼級的元數(shù)據(jù)類型” 章節(jié)中將會對這些屬性詳細講解。
你是不是也發(fā)現(xiàn)了 age
和 name
屬性都被 ManagedAttribute
注解了呢,但是對于 age
屬性,僅僅getter給標識了。這使得管理接口也將這些屬性包含進去,只是 age
屬性將是只讀的。
最后,你也注意到 add(int, int)
被 ManagedOperation
標識了,dontExposeMe()
卻沒有。
這使得使用 MetadataMBeanInfoAssembler
時,管理接口僅包含add(int, int)
方法。
下面代碼顯示了如何使用 MetadataMBeanInfoAssembler
來配置 MBeanExporter
。
<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="assembler" ref="assembler"/> </bean> <bean id="testBean" class="org.springframework.jmx.JmxTestBean"> <property name="name" value="TEST"/> <property name="age" value="100"/> </bean> <bean id="attributeSource" class="org.springframework.jmx.export.metadata.AttributesJmxAttributeSource"> <property name="attributes"> <bean class="org.springframework.metadata.commons.CommonsAttributes"/> </property> </bean> <bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler"> <property name="attributeSource" ref="attributeSource"/> </bean> </beans>
這里你看到了 MetadataMBeanInfoAssembler
Bean被配置了一個 AttributesJmxAttributeSource
類的實例,并且通過assembler屬性將之注入到 MBeanExporter
當中。為通過Spring暴露的MBean得到元數(shù)據(jù)驅(qū)動的管理接口的好處,要做的事情就是這么多了。
為了激活JDK 5.0的注解,用它來管理接口定義,Spring提供了一套相當于Commons Attribute注解和一個策略接口 JmxAttributeSource
的實現(xiàn)類 AnnotationsJmxAttributeSource
,這個類可以讓 MBeanInfoAssembler
讀取這些注解。
下例用JDK 5.0注解類型定義了一個管理接口Bean:
package org.springframework.jmx; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.annotation.ManagedAttribute; @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 implements IJmxTestBean { private String name; private int age; @ManagedAttribute(description="The Age Attribute", currencyTimeLimit=15) public int getAge() { return age; } public void setAge(int age) { this.age = 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 name; } @ManagedOperation(description="Add two numbers") @ManagedOperationParameters({ @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(); } }
看到了吧,除了元數(shù)據(jù)定義的基本語法外,改動很小。這種方法在啟動時相對慢些, 因為JDK 5.0的注解要轉(zhuǎn)換為Commons Attributes使用的類。盡管如此,這也只是 一次性的開銷,JDK 5.0注解給了編譯時檢查的額外好處。
<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>
<bean id="jmxAttributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
<!-- 這會使用注解元數(shù)據(jù)創(chuàng)建管理接口 -->
<bean id="assembler"
class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
<!-- 從注解中得到ObjectName
-->
<bean id="namingStrategy"
class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
<bean id="testBean" class="org.springframework.jmx.AnnotationTestBean">
<property name="name" value="TEST"/>
<property name="age" value="100"/>
</bean>
</beans>
Spring JMX中,可用使用以下源代碼級的元數(shù)據(jù)類型:
表?20.2.?源代碼級的元數(shù)據(jù)類型
用途 | Commons Attributes屬性 | JDK 5.0注解 | 屬性/注解類型 |
---|---|---|---|
將類的所有實例標識為JMX受控資源 | ManagedResource |
@ManagedResource |
Class 類 |
將方法標識為JMX操作 | ManagedOperation |
@ManagedOperation |
Method方法 |
將getter或者setter標識為部分JMX屬性 | ManagedAttribute |
@ManagedAttribute |
Method (only getters and setters) 方法(僅getters和setters) |
定義操作參數(shù)說明 | ManagedOperationParameter |
@ManagedOperationParameter 和 @ManagedOperationParameters
|
Method 方法 |
源代碼級的元數(shù)據(jù)類型可以使用以下配置參數(shù):
表?20.3.?源代碼級的元數(shù)據(jù)參數(shù)
參數(shù) | 描述 | 應(yīng)用于 |
---|---|---|
ObjectName |
MetadataNamingStrategy 用其來決定一個受控資源的 ObjectName
|
ManagedResource |
說明 |
設(shè)置資源,屬性,操作的說明 |
ManagedResource 、
ManagedAttribute 、
ManagedOperation 、
ManagedOperationParameter
|
currencyTimeLimit |
設(shè)置 currencyTimeLimit 描述符字段的值 currencyTimeLimit
|
ManagedResource 、ManagedAttribute
|
defaultValue |
設(shè)置 defaultValue 描述符字段的值 |
ManagedAttribute |
log |
設(shè)置 log 描述符字段的值 |
ManagedResource |
logFile |
設(shè)置 logFile 描述符字段的值 |
ManagedResource |
persistPolicy |
設(shè)置 persistPolicy 描述符字段的值 |
ManagedResource |
persistPeriod |
設(shè)置 persistPeriod 描述符字段的值 |
ManagedResource |
persistLocation |
設(shè)置 persistLocation 描述符字段的值 |
ManagedResource |
persistName |
設(shè)置 persistName 描述符字段的值 |
ManagedResource |
name |
設(shè)置操作參數(shù)的顯示名稱 | ManagedOperationParameter |
index |
設(shè)置操作參數(shù)的索引 | ManagedOperationParameter |
為了進一步簡化配置,Spring引入了 AutodetectCapableMBeanInfoAssembler
接口,
它擴展了 MBeanInfoAssembler
接口,增加了自動探測MBean資源的支持。
如果你用一個 AutodetectCapableMBeanInfoAssembler
實例配置了 MBeanExporter
,那么它就可以對要暴露給JMX的所有Bean的進行表決。
AutodetectCapableMBeanInfo
現(xiàn)成的唯一實現(xiàn)是 MetadataMBeanInfoAssembler
,它“表決”將所有標識了 ManagedResource
屬性的Bean包含在內(nèi)。
這種情況的缺省方法是用bean的名稱作為 ObjectName
,這樣,我們就得到了這樣一份配置:
<beans>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<!-- 這里,注意怎樣才不顯示配置 'beans'
-->
<property name="autodetect" value="true"/>
<property name="assembler" ref="assembler"/>
</bean>
<bean id="testBean" class="org.springframework.jmx.JmxTestBean">
<property name="name" value="TEST"/>
<property name="age" value="100"/>
</bean>
<!-- (對于Commons Attributes-based metadata) -->
<bean id="attributeSource"
class="org.springframework.jmx.export.metadata.AttributesJmxAttributeSource">
<property name="attributes">
<bean class="org.springframework.metadata.commons.CommonsAttributes"/>
</property>
</bean>
<!-- (對于基于注解的JDK5+元數(shù)據(jù)) -->
<!--
<bean id="attributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
-->
<bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="attributeSource"/>
</bean>
</beans>
注意,在這份配置中,MBeanExporter
沒有配置任何Bean,
然而,由于 JmxTestBean
用 ManagedResource
屬性做了標識,
MetadataMBeanInfoAssembler
探測到且表決將要包含它,因此它仍會被注冊。
這種方法的唯一問題是,現(xiàn)在的 JmxTestBean
有了業(yè)務(wù)含義。
這個問題可以通過 第?20.4?節(jié) “控制Bean的ObjectName
” 定義那樣改變 ObjectName
創(chuàng)建的默認行為來解決。
除了 MetadataMBeanInfoAssembler
,Spring還包含了 InterfaceBasedMBeanInfoAssembler
,它可以根據(jù)一組接口定義的方法限定要暴露的方法和屬性。
雖然使用接口和簡單的命名規(guī)則是暴露MBean的標準方式,但是 InterfaceBasedMBeanInfoAssembler
擴展這個功能,去除了命名約定,使得你不但可以使用多個接口,還可以省去實現(xiàn)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>
你可以看到,當為任意Bean構(gòu)建管理接口時,InterfaceBasedMBeanInfoAssembler
配置了使用 IJmxTestBean
接口。
由 InterfaceBasedMBeanInfoAssembler
處理的bean不需要實現(xiàn)用來產(chǎn)生JMX管理接口的接口,明白這一點很很重要。
在上面例子中,IJmxTestBean
被用來構(gòu)建所有bean的管理接口。
很多情況下,在你想對不同的Bean使用不同接口時就不想這樣了。
這時,你可以給 InterfaceBasedMBeanInfoAssembler
通過 interfaceMappings
屬性傳遞一個 Properties
實例。每個條目的鍵值是Bean的名字,條目的值一個以逗號(;)隔開,使用于該Bean的的接口名稱列表。
如果沒有通過 managedInterfaces
和 interfaceMappings
屬性指定管理接口,InterfaceBasedMBeanInfoAssembler
將通過反射,使用該Bean實現(xiàn)的所有接口來產(chǎn)生管理接口。
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()
將被暴露成對應(yīng)的JMX屬性。以上代碼使用與那些暴露到JMX的Bean。
要控制基于一個一個Bean的方法暴露,就要使用 MethodNameMBeanInfoAssembler
的 methodMappings
屬性來將Bean名字映射到方法名稱列表上了。