JMX在Tomcat中的應用(四)

四、 Tomcat 中最簡單的 MBean

下面我們打開 Tomcat 源代碼,看看 Tomcat 中最簡單的一個 MBean 。在 Tomcat 的啓動引導類 Bootstrap.java 172 187 行,我們可以看到如下代碼:

ClassLoader classLoader = ClassLoaderFactory.createClassLoader
(locations, types, parent);

// Retrieving MBean server
MBeanServer mBeanServer = null;
if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
mBeanServer =
  (MBeanServer) MBeanServerFactory.findMBeanServer(null).get(0);
} else {
mBeanServer = MBeanServerFactory.createMBeanServer();
}

// Register the server classloader
ObjectName objectName =
new ObjectName("Catalina:type=ServerClassLoader,name=" + name);
mBeanServer.registerMBean(classLoader, objectName);


4.1
上面的代碼首先使用 ClassLoaderFactory 工廠類創建一個 ClassLoader

4.2 然後在 MBeanServerFactory 這個工廠類中查找 MBeanServer ,如果沒有發現,就使用這個工廠類創建一個 MBeanServer

4.3 第三步是給剛纔創建的 ClassLoader 這個 MBean 取個名字“ Name: Catalina:type=ServerClassLoader,name=common ”,然後註冊到 MBeanServer

您如果在 JConsole 中觀察這個 MBean ,會發現這個 MBean 沒有向管理應用程序暴露任何屬性和方法,並且 Classloader 似乎也符合 JMX 命名規範,它也不是一個 DynamicBean ,這是爲什麼呢?首先,這個 Classloader 其實一個 StandardClassloader ,而不是 JDK 中缺省的 Classloader ,您如果打開 ClassLoaderFactory createClassLoader 方法,馬上就可以看到這一點;另外,看看 StanderClassloader 的類簽名,我們會發現該類實現了 StandardClassLoaderMBean 接口,這是符合 JMX 命名規範的;請打開 StandardClassLoaderMBean 接口的源代碼,您會發現這是一個空接口,這意味着實現這個接口的 MBean 不會向管理程序暴露任何屬性和方法。

最後,希望這篇入門級的簡單介紹,能有助於大家理解 JMX JMX Tomcat 中的應用。















附錄:針對本文中的熱水器小例子,我們給出了一個簡單問題,即如何修改我們既有的代碼,讓這些代碼所在的資源能使用
JMX 管理?如果您稍微翻閱一下 Tomcat 的源代碼,您會發現, Tomcat 的作者們在 JMX 升級時對已有源代碼的改動有點粗暴,勇猛有餘,優美不足。 org.apache.catalina.core 包中的關鍵組件,大部分後加了 preRegister() getObjectName() 等等方法,在 init() 方法中又添加了一堆 Registry.getRegistry.unregisterComponent registerComponent 代碼,這些方法其實這些 core 組件沒有直接關係,也不是這些 core 組件應該具有的功能,並且這些後添加的代碼及其類似。當然,這種情況在我們實際項目中更爲多見,主要原因是時間不足,資源有限等等。

如果要比較優美的解決上面的問題,我個人認爲,首先,保持現有代碼,然後對現有代碼進行擴展而不是大刀闊斧的修改已有代碼。就拿我們熱水器的簡單例子來說,我們不要修改 CentralHeaterImpl.java 的現有代碼,而是使用 Wrapper 設計模式,設計一個新類,然後將這個 CentralHeaterImpl 類適配成我們需要的 MBean 接口,具體實現如下:


a)   CentralHeaterDecoratorMBean.java 源代碼

package
carl.test.jmx;
/**
* @author carlwu
*
*/
public interface CentralHeater Decorator MBean {

/**
* return the heater provider
* @return
*/
public String getHeaterProvider();


/**
* Get current temperature of heater
* @return the temperature of the heater
*/
public int getCurrentTemperature();

/**
* Set the new temperature
* @param newTemperature
*/
public void setCurrentTemperature( int newTemperature);

}

CentralHeaterDecorator .java 的源代碼:

package
carl.test.jmx;
public class CentralHeaterDecorator implements CentralHeaterDecoratorMBean {

private CentralHeaterImpl centralHeater ;

public CentralHeaterDecorator(CentralHeaterImpl theCentralHeater){
centralHeater =theCentralHeater;
}


public int getCurrentTemperature() {
// TODO Auto-generated method stub
return centralHeater .getCurrentTemperature();
}

public void setCurrentTemperature( int newTemperature) {
// TODO Auto-generated method stub
centralHeater .setCurrentTemperature(newTemperature);
}



public String getHeaterProvider() {
// TODO Auto-generated method stub
return centralHeater . HEATER_PROVIDER ;
}


public String printCurrentTemperature() {
// TODO Auto-generated method stub
String returnMsg = "Current temperature is:"
    + centralHeater .getCurrentTemperature();
System. out .println(returnMsg);
return returnMsg;

}

}



最後,請把 Agent 代碼中的下面一行:

CentralHeaterInf centralHeater =
new CentralHeaterImpl();

改爲:

CentralHeaterDecoratorMBean centralHeater = new CentralHeaterDecorator(new CentralHeaterImpl());

其運行效果完全一樣,但我們完全沒有改動既有代碼。

發佈了33 篇原創文章 · 獲贊 0 · 訪問量 1873
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章