中秋归来,这篇分析tomcat关于jmx的部分,tomcat用的是DynamicMBean,不熟悉JMX的同学可以网上看下,上篇文章分析了tomcat的Catalina类,了解到Catalina会调用StandardServer,现在看下StandardServer的继承关系
这篇文章重点看LifecycleMBeanBase,他是跟JMX相关的部分,先看下接口Lifecycle,看名字可以知道是跟生命周期相关的接口,下面方法是跟添加Listener相关方法
public void addLifecycleListener(LifecycleListener listener);
public LifecycleListener[] findLifecycleListeners();
public void removeLifecycleListener(LifecycleListener listener);
下面方法是跟生命周期相关的回调方法,init,start,stop ,destroy
public void init() throws LifecycleException;
public void start() throws LifecycleException;
public void stop() throws LifecycleException;
public void destroy() throws LifecycleException;
LifecycleBase类是简单对Lifecycle接口的实现。
现在重点看下LifecycleMBeanBase类,重点看initInternal方法,destroyInternal方法,domain和ObjectName属性,这两个属性跟JMX直接相关,先看下getDomain方法
public final String getDomain() {
if (domain == null) {
//调用抽象方法 getDomainInternal,getDomainInternal方法需要JMX管理的类覆盖
domain = getDomainInternal();
}
if (domain == null) {
//默认用DEFAULT_MBEAN_DOMAIN
domain = Globals.DEFAULT_MBEAN_DOMAIN;
}
return domain;
}
ObjectName属性相关的方法initInternal,destroyInternal
protected void initInternal() throws LifecycleException {
if (oname == null) {
mserver = Registry.getRegistry(null, null).getMBeanServer();
//注册得到ObjectName
oname = register(this, getObjectNameKeyProperties());
}
}
protected void destroyInternal() throws LifecycleException {
//注销ObjectName
unregister(oname);
}
在看下register方法, unregister方法注销MBean
protected final ObjectName register(Object obj,
String objectNameKeyProperties) {
StringBuilder name = new StringBuilder(getDomain());
name.append(':');
name.append(objectNameKeyProperties);
ObjectName on = null;
try {
// 实例化ObjectName,getDomain,objectNameKeyProperties需要之类覆写,有了ObjectName就可以用来在Server上注册MBean
on = new ObjectName(name.toString());
Registry.getRegistry(null, null).registerComponent(obj, on, null);
} catch (MalformedObjectNameException e) {
log.warn(sm.getString("lifecycleMBeanBase.registerFail", obj, name),
e);
} catch (Exception e) {
log.warn(sm.getString("lifecycleMBeanBase.registerFail", obj, name),
e);
}
return on;
}
上面的方法可以看到Registry类,tomcat跟JMX相关的主要类,看Registry类方法之前先看类GlobalResourcesLifecycleListener、MBeanUtils。GlobalResourcesLifecycleListener类
上图可以看到server.xml配置,再看Catalina类的createDigester方法,上篇分析可以知道Catalina类的createDigester方法内容是解析server.xml的配置
可以知道会调用Server上的addLifecycleListener方法传入LifecycleListener,主要看GlobalResourcesLifecycleListener类的属性
protected static final Registry registry = MBeanUtils.createRegistry();
可以看到类MBeanUtils,现在看createRegistry方法,createRegistry方法会调用Rigestry的loadDescriptors方法,加载org.apache.catalina下一系列的MBean描述, loadDescriptors方法会去相对应的包下加载mbeans-descriptors.xml配置,loadDescriptors方法调用load方法去实际加载MBean描述,
方法调用链loadDescriptors->load("MbeansDescriptorsDigesterSource", dURL, null),Load方法根据传入的参数获取ModelerSource类,调用ModelerSource类的loadDescriptors(Registry, type, inputsource)方法,ModelerSource继承关系。
这条线会调用MbeansDescriptorsDigesterSource的loadDescriptors方法加载MBean描述,我们可以看到createDigester方法,可以熟悉的看到跟Catalina类相似的代码,Digester那篇分析过,现在看下loadDescriptors方法-> execute方法
public void execute() throws Exception {
if (registry == null) {
registry = Registry.getRegistry(null, null);
}
InputStream stream = (InputStream) source;
ArrayList<ManagedBean> loadedMbeans = new ArrayList<>();
synchronized(dLock) {
if (digester == null) {
//配置解析包下的mbeans-descriptors.xml文件
digester = createDigester();
}
try {
//push loadedMbeans
digester.push(loadedMbeans);
//开始解析
digester.parse(stream);
} catch (Exception e) {
log.error("Error digesting Registry data", e);
throw e;
} finally {
digester.reset();
}
}
//调用registry.addManagedBean,传入ManageBean
Iterator<ManagedBean> iter = loadedMbeans.iterator();
while (iter.hasNext()) {
registry.addManagedBean(iter.next());
}
}
现在我们简单的看下createDigester和对应的mbeans-descriptors.xml,以org\apache\catalina\mbeans-descriptors.xml为例子,自己可以打开看
//解析到mbeans-descriptors/mbean,实例化ManagedBean类
digester.addObjectCreate
("mbeans-descriptors/mbean",
"org.apache.tomcat.util.modeler.ManagedBean");
//设置mbeans-descriptors/mbean的attribute给ManagedBean类
digester.addSetProperties
("mbeans-descriptors/mbean");
//调用loadedMbeans的add方法传入ManagedBean
digester.addSetNext
("mbeans-descriptors/mbean",
"add",
"java.lang.Object");
//解析到mbeans-descriptors/mbean/attribute,实例化类AttributeInfo
digester.addObjectCreate
("mbeans-descriptors/mbean/attribute",
"org.apache.tomcat.util.modeler.AttributeInfo");
//设置mbeans-descriptors/mbean/attribute的attribute给AttributeInfo类
digester.addSetProperties
digester.addSetProperties
("mbeans-descriptors/mbean/attribute");
digester.addSetNext
("mbeans-descriptors/mbean/attribute",
"addAttribute",
"org.apache.tomcat.util.modeler.AttributeInfo");
以下类推
…………………………………
总之parse最后的结果是,Registry类加载了mbeans-descriptors.xml配置下的ManagedBean。
现在在看MbeansDescriptorsIntrospectionSource类,loadDescriptors->execute->createManagedBean方法,根据Class类创建ManagedBean,add进Registry。
现在回头看Registry类的registerComponent和unregisterComponent方法
主要看registerComponent方法,registerComponent方法findManagedBean ,找到对应的ManagedBean ,然后ManagedBean.createMBean ,getMBeanServer().registerMBean( mbean, oname)。
总结:跟tomcat JMX相关的主要是Registry,GlobalResourcesLifecycleListener->Registry.createRegistry->解析包下的mbeans-descriptors.xml配置,Registry.addManageBean,
当initInternal 方法register的时候,会获取ManageBean,当找不到ManageBean的时候,会通过MbeansDescriptorsIntrospectionSource 来创建ManageBean,然后调用ManageBean. createMBean,注册DynamicMBean。
版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: