?
このドキュメントでは、 php中國(guó)語ネットマニュアル リリース
Spring的JMX框架的核心類是 MBeanExporter
。這個(gè)類負(fù)責(zé)獲取Spring Bean,
然后將其注冊(cè)到一個(gè)JMX MBeanServer
上。例如,仔細(xì)看看以下這幾個(gè)類:
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(); } }
要將一個(gè)Bean中的屬性和方法暴露成為一個(gè)JMX MBean中的屬性和操作,你只要在配置文件中簡(jiǎn)單的配置 MBeanExporter
一個(gè)實(shí)例,并且按照如下方法將這個(gè)Bean傳入:
<beans> <!-- 如果要暴露,這個(gè)Bean一定 不 可以延遲初始化。--> <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>
上述配置片段中,關(guān)系最大的是 exporter
Bean。beans
屬性使得
MBeanExporter
知道要將哪個(gè)Bean輸出到JMX的 MBeanServer
上去。
缺省配置中,beans
里的 Map
中的條目的key被用作相應(yīng)條目值所引用的Bean的 ObjectName
。
可以按照 第?20.4?節(jié) “控制Bean的ObjectName
” 描述的那樣改變這種行為。
在這個(gè)配置里,testBean
就以 bean:name=testBean1
這個(gè) ObjectName
暴露成了一個(gè)MBean。
默認(rèn)情況下,Bean中所有 public 的屬性被暴露為屬性,所有的 public 方法(除了那些從 Object
類繼承過來的之外)都被暴露為操作。
上述配置是假設(shè)了應(yīng)用程序運(yùn)行在這樣的環(huán)境中,一個(gè)有且僅有一個(gè)在運(yùn)作中的 MBeanServer
的環(huán)境。
這種情況下,Spring將試圖定位該 MBeanServer
,之后將你的Bean(如果有的話)注冊(cè)到該服務(wù)器上。
在自帶 MBeanServer
的容器(例如Tomcat或者IBM WebSphere)中,這種行為是很有用的。
然而,在一個(gè)孤立的環(huán)境,或者不提供 MBeanServer
的容器中,這種方法毫無用武之地。
要處理這類問題,你應(yīng)該創(chuàng)建一個(gè) MBeanServer
實(shí)例,也就是聲明式地將 org.springframework.jmx.support.MBeanServerFactoryBean
實(shí)例添加到你的配置里。
通過設(shè)置 MBeanExporter
的 server
屬性的值,
你也可以確保 MBeanExporter
使用了 MBeanServerFactoryBean
返回的特定的 MBeanServer
。
例如:
<beans>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
<!--
要觸發(fā)輸出,必須預(yù)先實(shí)例化這個(gè)Bean,一定 不 可以標(biāo)志為延遲初始化。
-->
<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>
這里有一個(gè)由 MBeanServerFactoryBean
創(chuàng)建的 MBeanServer
實(shí)例,它通過屬性server提供給了 MBeanExporter
。
當(dāng)你提供了你自己的 MBeanServer
實(shí)例后,MBeanExporter
將使用該實(shí)例,且不再查找一個(gè)運(yùn)行中的 MBeanServer
。為了使之正確工作,當(dāng)然了,你必須確保你的類路徑上存在一個(gè)JMX實(shí)現(xiàn)。
如果不指定任何服務(wù)器,MBeanExporter
將自動(dòng)檢測(cè)一個(gè)運(yùn)行中的 MBeanServer
。
這在只有一個(gè) MBeanServer
的情況下可以奏效,當(dāng)存在多個(gè) MBeanServer
的時(shí)候,
MBeanExporter
可能會(huì)選錯(cuò)服務(wù)器。這種情況下,應(yīng)該使用 MBeanServer
的 agentId
來指定究竟使用哪個(gè)服務(wù)器。
<beans>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
<!-- 說明首先要查找一個(gè)服務(wù)器 -->
<property name="locateExistingServerIfPossible" value="true"/>
<!-- 根據(jù)給定的agentId查找對(duì)應(yīng)的 MBeanServer
實(shí)例 -->
<property name="agentId" value="<MBeanServer instance agentId>"/>
</bean>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="server" ref="mbeanServer"/>
...
</bean>
</beans>
在某些平臺(tái)中,MBeanServer
有一個(gè)動(dòng)態(tài)(或者未知)的要通過lookup方法獲取的 agentId
。
這時(shí)就應(yīng)該用 factory-method。
<beans>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="server">
<!-- 自定義MBeanServerLocator
-->
<bean class="platform.package.MBeanServerLocator" factory-method="locateMBeanServer"/>
</property>
<!-- 其他Bean -->
</bean>
</beans>
如果你在 MBeanExporter
上配置了一個(gè)Bean,而這個(gè) MBeanExporter
又配置了延遲初始化,那么 MBeanExporter
遵循這種契約,避免初始化這個(gè)Bean。相反,它會(huì)在 MBeanServer
上注冊(cè)一個(gè)代理,推延從容器獲取這個(gè)Bean的時(shí)刻,直到在代理端發(fā)生對(duì)它的第一次調(diào)用。
要通過 MBeanExporter
輸出的任意的Bean,并已是有效的MBean,將會(huì)被注冊(cè)到 MBeanServer
上去,而無須Spring的干預(yù)。
通過設(shè)置屬性 autodetect
的值為true,MBeanExporter
將會(huì)自動(dòng)探測(cè)MBean,如下:
<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就已經(jīng)是一個(gè)有效的JMX MBean了。它將會(huì)被Spring自動(dòng)注冊(cè)。
缺省情況下,那些做自動(dòng)JMX注冊(cè)的Bean的 ObjectName
就是它的Bean名稱。
標(biāo)題為 第?20.4?節(jié) “控制Bean的ObjectName
” 的章節(jié)里詳細(xì)的描述了如何覆蓋(overridden)這種行為。
考慮這樣的場(chǎng)景,一個(gè)Spring MBeanExporter
試圖用 ObjectName
'bean:name=testBean1'
向 MBeanServer
注冊(cè)一個(gè)MBean。
如果已經(jīng)存在一個(gè)同樣 ObjectName
的 MBean
實(shí)例,缺省行為是失?。ú⑶覓伋鲆粋€(gè) InstanceAlreadyExistsException
)。
MBean
時(shí)發(fā)生哪種行為。
Spring的JMX支持提供三種不同的注冊(cè)行為,以此來控制注冊(cè)進(jìn)程發(fā)現(xiàn)一個(gè) MBean
已經(jīng)用同樣的 ObjectName
注冊(cè)的情況。下面的表格總結(jié)了這些注冊(cè)行為:
表?20.1.?注冊(cè)行為
注冊(cè)行為 | 說明 |
---|---|
|
這是缺省的注冊(cè)行為。如果一個(gè) |
|
如果一個(gè) |
|
如果一個(gè) |
MBeanRegistrationSupport
類以常量的方式定義了上述這些值(MBeanExporter
繼承了這個(gè)父類)。如果你向改變?nèi)笔〉淖?cè)行為,你只需要將 MBeanExporter
的屬性 registrationBehaviorName
的值設(shè)置為上述這些值之一。
以下例子闡明了如何將缺省注冊(cè)行為改變?yōu)?REGISTRATION_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="registrationBehaviorName" value="REGISTRATION_REPLACE_EXISTING"/> </bean> <bean id="testBean" class="org.springframework.jmx.JmxTestBean"> <property name="name" value="TEST"/> <property name="age" value="100"/> </bean> </beans>