tomcat源码分析之Observer模式以及应用加载--Lifecycle
研究过tomcat源码的朋友们可能都发现了,tomcat中几个主要的component都实现了Lifecycle接口,并且在start的时候通常都会publish一些事件。在这个过程中tomcat是通过Observer模式来实现相关功能的。下面以StandardHost为例来说明。
StandardHost是StandardContext(也就是部署在tomcat下面的一个个应用)的上级Container.Host是在Digester server.xml文件的时候生成的。但是,在digester的时候,并没有standardcontext的相关配置。那么,StandardContext是如何加载的呢?
下面就来研究一下standardhost的源码:
先来看init源码:
public void init() {
if( initialized ) return;
initialized=true;
// already registered.
if( getParent() == null ) {
try {
// Register with the Engine
ObjectName serviceName=new ObjectName(domain +
":type=Engine");
HostConfig deployer = new HostConfig();
addLifecycleListener(deployer);
if( mserver.isRegistered( serviceName )) {
if(log.isDebugEnabled())
log.debug("Registering "+ serviceName +" with the Engine");
mserver.invoke( serviceName, "addChild",
new Object[] { this },
new String[] { "org.apache.catalina.Container" } );
}
} catch( Exception ex ) {
log.error("Host registering failed!",ex);
}
}
if( oname==null ) {
// not registered in JMX yet - standalone mode
try {
StandardEngine engine=(StandardEngine)parent;
domain=engine.getName();
if(log.isDebugEnabled())
log.debug( "Register host " + getName() + " with domain "+ domain );
oname=new ObjectName(domain + ":type=Host,host=" +
this.getName());
controller = oname;
Registry.getRegistry(null, null)
.registerComponent(this, oname, null);
} catch( Throwable t ) {
log.error("Host registering failed!", t );
}
}
}
StandardHost本身是一个container(ContainerBase),从以上代码可以看出,它在初始化的时候注册了一个LifecycleListener:HostConfig. 不同于一般的Observer模式的地方是,standard并不直接拥有listeners,而是通过拥有一个工具类-LifecycleSupport来维护与listeners的关系。这样就使得代码看起来很干净。已经注册了Observer,那么在哪里触发事件呢?事件触发是在container启动的时候(其实观察tomcat6中的重要组件,比如standardserver,standardservice以及container如standardengine,standardhost,standardcontext,他们在start的时候都会发布这么几个事件:beforestartevent,startevent,afterstartevent). 于是在standardhost start的时候,触发事件,listeners作出响应,hostconfig的响应代码如下:
public void lifecycleEvent(LifecycleEvent event) {
if (event.getType().equals(Lifecycle.PERIODIC_EVENT))
check();
// Identify the host we are associated with
try {
host = (Host) event.getLifecycle();
if (host instanceof StandardHost) {
setDeployXML(((StandardHost) host).isDeployXML());
setUnpackWARs(((StandardHost) host).isUnpackWARs());
setXmlNamespaceAware(((StandardHost) host).getXmlNamespaceAware());
setXmlValidation(((StandardHost) host).getXmlValidation());
}
} catch (ClassCastException e) {
log.error(sm.getString("hostConfig.cce", event.getLifecycle()), e);
return;
}
// Process the event that has occurred
if (event.getType().equals(Lifecycle.START_EVENT))
start();
else if (event.getType().equals(Lifecycle.STOP_EVENT))
stop();
}
可以看出,如果触发的事件是START_EVENT,那么hostconfig调用自己的start方法。而正是在
start方法里面,调用deployApps来生成standardContext.
至此,不仅了解了tomcat中Lifecycle的Observer模式,而且了解了tomcat加载应用的流程。可谓一举两得。
页:
[1]