锁定老帖子 主题:Tomcat生命周期管理
精华帖 (1) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (2)
|
|
---|---|
作者 | 正文 |
发表时间:2010-06-19
最后修改:2010-06-19
在之前的 Tomcat 整体架构中可以看到 Tomcat 包含多个很多个组件 , 今天我们来看看, Tomcat 是如何管理这些组件的生命周期的。 …… 2010-6-19 15:41:18 org.apache.catalina.core.StandardService start 信息 : Starting service Catalina 2010-6-19 15:41:18 org.apache.catalina.core.StandardEngine start 信息 : Starting Servlet Engine: Apache Tomcat/6.0.18 … 2010-6-19 15:41:19 org.apache.coyote.http11.Http11Protocol start 信息 : Starting Coyote HTTP/1.1 on http-8080 2010-6-19 15:41:19 org.apache.jk.common.ChannelSocket init 信息 : JK: ajp13 listening on /0.0.0.0:8009 2010-6-19 15:41:19 org.apache.jk.server.JkMain start 信息 : Jk running ID=0 time=0/182 config=null 2010-6-19 15:41:19 org.apache.catalina.startup.Catalina start 信息 : Server startup in 1706 ms
StandardService --> StandardEngine-->Http11Protocol-->JkMain-->Catalina
package org.apache.catalina; public interface Lifecycle { public static final String INIT_EVENT = "init"; public static final String START_EVENT = "start"; public static final String BEFORE_START_EVENT = "before_start"; public static final String AFTER_START_EVENT = "after_start"; public static final String STOP_EVENT = "stop"; public static final String BEFORE_STOP_EVENT = "before_stop"; public static final String AFTER_STOP_EVENT = "after_stop"; public static final String DESTROY_EVENT = "destroy"; public static final String PERIODIC_EVENT = "periodic"; public void addLifecycleListener(LifecycleListener listener); public LifecycleListener[] findLifecycleListeners(); public void removeLifecycleListener(LifecycleListener listener); public void start() throws LifecycleException; public void stop() throws LifecycleException; }
另外生命周期的相关事件,定义在 LifecycleEvent 类中
package org.apache.catalina; import java.util.EventObject; public final class LifecycleEvent extends EventObject { // ----------------------------------------------------------- Constructors public LifecycleEvent(Lifecycle lifecycle, String type) { this(lifecycle, type, null); } public LifecycleEvent(Lifecycle lifecycle, String type, Object data) { super(lifecycle); this.lifecycle = lifecycle; this.type = type; this.data = data; } private Object data = null; private Lifecycle lifecycle = null; private String type = null; public Object getData() { return (this.data); } public Lifecycle getLifecycle() { return (this.lifecycle); } public String getType() { return (this.type); } }
关于事件的监听,在接口LifecycleListener 中有定义
package org.apache.catalina; public interface LifecycleListener { public void lifecycleEvent(LifecycleEvent event); }
另外,这里还需要介绍一个特别的类:LifecycleSupport, 用于触发生命周期的相关事件.
package org.apache.catalina.util; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleListener; public final class LifecycleSupport { public LifecycleSupport(Lifecycle lifecycle) { super(); this.lifecycle = lifecycle; } private Lifecycle lifecycle = null; private LifecycleListener listeners[] = new LifecycleListener[0]; private final Object listenersLock = new Object(); // Lock object for changes to listeners public void addLifecycleListener(LifecycleListener listener) { synchronized (listenersLock) { LifecycleListener results[] = new LifecycleListener[listeners.length + 1]; for (int i = 0; i < listeners.length; i++) results[i] = listeners[i]; results[listeners.length] = listener; listeners = results; } } public LifecycleListener[] findLifecycleListeners() { return listeners; } public void fireLifecycleEvent(String type, Object data) { LifecycleEvent event = new LifecycleEvent(lifecycle, type, data); LifecycleListener interested[] = listeners; for (int i = 0; i < interested.length; i++) interested[i].lifecycleEvent(event); } public void removeLifecycleListener(LifecycleListener listener) { synchronized (listenersLock) { int n = -1; for (int i = 0; i < listeners.length; i++) { if (listeners[i] == listener) { n = i; break; } } if (n < 0) return; LifecycleListener results[] = new LifecycleListener[listeners.length - 1]; int j = 0; for (int i = 0; i < listeners.length; i++) { if (i != n) results[j++] = listeners[i]; } listeners = results; } } }
下面,我们来看看 StandardService 类的启动方法, 看它是如何启动的 在service真正启动时,他首先会触发一些启动前的事件, public class StandardService implements Lifecycle, Service, MBeanRegistration { ............. /** * The lifecycle event support for this component. */ private LifecycleSupport lifecycle = new LifecycleSupport(this); ............. /** * The set of Connectors associated with this Service. 关联到这个Service的连接器对象. */ protected Connector connectors[] = new Connector[0]; public void start() throws LifecycleException { // Validate and update our current component state if (log.isInfoEnabled() && started) { log.info(sm.getString("standardService.start.started")); } if( ! initialized ) init(); // 触发启动之前的事件 lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); if(log.isInfoEnabled()) log.info(sm.getString("standardService.start.name", this.name)); lifecycle.fireLifecycleEvent(START_EVENT, null); <<<<(1) started = true; // Start our defined Container first 首先启动关联的容器 if (container != null) { synchronized (container) { if (container instanceof Lifecycle) { ((Lifecycle) container).start(); } } } synchronized (executors) { for ( int i=0; i<executors.size(); i++ ) { executors.get(i).start(); } } // Start our defined Connectors second 再启动关联的连接器 synchronized (connectors) { for (int i = 0; i < connectors.length; i++) { if (connectors[i] instanceof Lifecycle) ((Lifecycle) connectors[i]).start(); } } // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null); }
代码(1)处,显示出,在Service正式启动之前,它还会出发启动前的事件,我们来看看,这个方法具体做些什么. 调用LifecycleSupport 类的 fireLifecycleEvent(START_EVENT, null);方法
public void fireLifecycleEvent(String type, Object data) { LifecycleEvent event = new LifecycleEvent(lifecycle, type, data); LifecycleListener interested[] = listeners; for (int i = 0; i < interested.length; i++) interested[i].lifecycleEvent(event); } 而在内部,Service启动时,这里真正调用的是类 ServerLifecycleListener的方法: package org.apache.catalina.mbeans; public class ServerLifecycleListener implements ContainerListener, LifecycleListener, PropertyChangeListener { public void lifecycleEvent(LifecycleEvent event) { Lifecycle lifecycle = event.getLifecycle(); if (Lifecycle.START_EVENT.equals(event.getType())) { if (lifecycle instanceof Server) { createMBeans(); } // We are embedded. if( lifecycle instanceof Service ) { try { //Service启动时,触发的事件 MBeanFactory factory = new MBeanFactory(); createMBeans(factory); createMBeans((Service)lifecycle); } catch( Exception ex ) { log.error("Create mbean factory"); } } /* // Ignore events from StandardContext objects to avoid // reregistering the context if (lifecycle instanceof StandardContext) return; createMBeans(); */ } else if (Lifecycle.AFTER_STOP_EVENT.equals(event.getType())) { try { if (lifecycle instanceof Server) { destroyMBeans((Server)lifecycle); } if (lifecycle instanceof Service) { destroyMBeans((Service)lifecycle); } } catch (MBeanException t) { Exception e = t.getTargetException(); if (e == null) { e = t; } log.error("destroyMBeans: MBeanException", e); } catch (Throwable t) { log.error("destroyMBeans: Throwable", t); } // FIXME: RMI adaptor should be stopped; however, this is // undocumented in MX4J, and reports exist in the MX4J bug DB that // this doesn't work } if ((Context.RELOAD_EVENT.equals(event.getType())) || (Lifecycle.START_EVENT.equals(event.getType()))) { // Give context a new handle to the MBean server if the // context has been reloaded since reloading causes the // context to lose its previous handle to the server if (lifecycle instanceof StandardContext) { // If the context is privileged, give a reference to it // in a servlet context attribute StandardContext context = (StandardContext)lifecycle; if (context.getPrivileged()) { context.getServletContext().setAttribute (Globals.MBEAN_REGISTRY_ATTR, MBeanUtils.createRegistry()); context.getServletContext().setAttribute (Globals.MBEAN_SERVER_ATTR, MBeanUtils.createServer()); } } } } }
这里简单介绍一下,Tomcat内部的启动流程, 通过观察者模式与监听器模式来作处理, 组件启动方面,在启动上级组件的同时,先启动下一级组件, (当然,在父组件内部,需要包含它所有子组件引用的一个集合). 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-06-21
不错
|
|
返回顶楼 | |
发表时间:2010-06-21
个人感觉Tomcat扩张不易,代码风格各异。
|
|
返回顶楼 | |
浏览 4589 次