`

3、tomcat中的设计模式。

阅读更多
这是我主要要写的内容,其中的模式主要是以GOF四人帮的教材作为参考,然后对tomcat中的源码做分析,从而从中分析一些设计模式出来。

1、Jmx的应用。
也即MBean的应用,用来处理对象的生存问题。
在tomcat里主要是要实现javax.management.MBeanRegistration这个接口,这就成为一个可注册组件。
abstract public interface MBeanRegistration{
    public ObjectName preRegister(MBeanServer server,
                                  ObjectName name) throws Exception ;
    public void postRegister(Boolean registrationDone);
    public void preDeregister() throws Exception ;
    public void postDeregister();
}


通过注册这个组件,就可以在需要的时候取来用。
 public void initialize()
        throws LifecycleException 
    {
        oname=new ObjectName( "Catalina:type=Server");
        Registry.getRegistry(null, null).registerComponent(this, oname, null );
    }


通过如下方法来读取文件的信息,来注册组件。
public class StandardEngine extends ContainerBase
                            implements Engine {
    public void init() {        
        if( mbeansFile == null ) {
            String defaultMBeansFile=getBaseDir() + "/conf/tomcat5-mbeans.xml";
            File f=new File( defaultMBeansFile );
            if( f.exists() ) mbeansFile=f.getAbsolutePath();
        }
        if( mbeansFile != null ) {
            readEngineMbeans();
        }
        if( mbeans != null ) {
            try {
                Registry.getRegistry(null, null).invoke(mbeans, "init", false);
            } catch (Exception e) {
                log.error("Error in init() for " + mbeansFile, e);
            }
        }
    }
    private void readEngineMbeans() {
        try {
            MbeansSource mbeansMB=new MbeansSource();
            File mbeansF=new File( mbeansFile );
            mbeansMB.setSource(mbeansF);
            
            Registry.getRegistry(null, null).registerComponent
                (mbeansMB, domain + ":type=MbeansFile", null);
            mbeansMB.load();
            mbeansMB.init();
            mbeansMB.setRegistry(Registry.getRegistry(null, null));
            mbeans=mbeansMB.getMBeans();
            
        } catch( Throwable t ) {
            log.error( "Error loading " + mbeansFile, t );
        }        
    }
}


可以通过如下方法来进行注册组件方法的调用。这个方法主要有两个功能,其一就是确保其父引用不为空,如为空,就调用注册组件的addChild()方法来设置父引用;其二就是注册自己。
public class StandardHost extends ContainerBase
                        implements Deployer, Host{
    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");
                
                if( mserver.isRegistered( serviceName )) {
                    log.debug("Registering with the Engine");
                    mserver.invoke( serviceName, "addChild",
                            new Object[] { this },
                            new String[] {"org.apache.catalina.Container" } );
                }
            } catch( Exception ex ) {
                ex.printStackTrace();
            }
        }
        
        if( oname==null ) {
            // not registered in JMX yet - standalone mode
            try {
                StandardEngine engine=(StandardEngine)parent;
                domain=engine.getName();
                log.debug( "Register " + domain );
                oname=new ObjectName(domain + ":type=Host,host=" +
                        this.getName());
                Registry.getRegistry(null, null)
                    .registerComponent(this, oname, null);
            } catch( Throwable t ) {
                log.info("Error registering ", t );
            }
        }
    }
}


2、Listener的应用。 主要为java中的事件处理,在java中事件处理从java1.1开始就用的是这种方式,Swing、AWT,SWT都是应用的这种事件模型。这里我举一些事例来说明tomcat中Listener的应用。
LifecycleListener接口处理:Lifecycle、LifecycleListener、LifecycleSupport、LifecycleEvent。
ContainerListener接口处理:Container,ContainerListener、ContainerEvent。
PropertyChangeListener接口处理:PropertyChangeListener、PropertyChangeSupport、PropertyChangeEvent、PropertyChangeListenerProxy。
这里以LifecycleListener接口处理为例:
public interface Lifecycle {
    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 void addLifecycleListener(LifecycleListener listener);
    public LifecycleListener[] findLifecycleListeners();
    public void removeLifecycleListener(LifecycleListener listener);
    public void start() throws LifecycleException;
    public void stop() throws LifecycleException;
}

public final class LifecycleSupport{
    public LifecycleSupport(Lifecycle lifecycle) ;
    private Lifecycle lifecycle = null;
    private LifecycleListener listeners[] = new LifecycleListener[0];
    public void addLifecycleListener(LifecycleListener listener) ;
    public LifecycleListener[] findLifecycleListeners() ;
    public void fireLifecycleEvent(String type, Object data) ;
    public void removeLifecycleListener(LifecycleListener listener);
}

public interface LifecycleListener {
    public void lifecycleEvent(LifecycleEvent event);
}


public final class LifecycleEvent extends EventObject {
    public LifecycleEvent(Lifecycle lifecycle, String type) ;
    public LifecycleEvent(Lifecycle lifecycle, String type, Object data) ;
    private Object data = null;
    private Lifecycle lifecycle = null;
    private String type = null;
    public Object getData() ;
    public Lifecycle getLifecycle() ;
    public String getType();
}


Lifecycle为事件源,即事件发生时将触发具体的事件。其中的addLifecycleListener(),和removeLifecycleListener(),负责对监听器进行注册和取消注册。start()和stop()为具体事件的触发源,当然也可以在其它地方触发事件,但这个地方为Lifecycle的接口,这地方最好。当调用start()后,将触发BEFORE_START_EVENT,START_EVENT,AFTER_START_EVENT事件。而stop()将调用BEFORE_STOP_EVENT,STOP_EVENT,AFTER_STOP_EVENT事件。

LifecycleListener为事件监听器,主要负责对事件源进行注册监听器,并监听事件源的触发事件。

LifecycleSupport为监听器LifecycleListener的保持者,也是具体的事件的最终触发者。其中包含一个LifecycleListener列表,当事件触发时,LifecycleSupport.fireLifecycleEvent()负责对LifecycleListener[]进行遍历,找出对应的监听器来触发具体的事件。

LifecycleEvent为具体的事件对象,也是事件触发后生成的事件对象,包含有事件源、事件类型、事件数据等信息。LifecycleListener.lifecycleEvent()运行时就是依靠LifecycleEvent来进行工作的。

3、Wrapper的应用。
tomcat中使用Wrapper对我们的servlet进行包装,使容器能够对我们自己写的servlet进行控制,也就是说用Wrapper来进行容器和我们的应用进行通信。
这个模式我还没有搞得清楚,具体情况见Wrapper接口和其具体实现StandardWrapper。


4、Facade的应用。
这里要谈的主要是servlet中消息的载体Request和Response中用Facade模式来处理sun规范中javax.servlet.Request和org.apache.catalina.Request之间的区别、javax.servlet.Response和org.apache.cataina.Response之间的区别。RequestFacade和ResponseFacde在这里起到了桥梁的作用。他既实现了javax.servlet.*的接口,又对org.apache.cataina.*进行包装,使*Facade对外就像javax.servlet.*一样。而其内部的实现又是通过org.apache.catanila.*来进行具体实现的,其对*Facade的任何请求都实际交给java.apahce.cataina.*来处理的。

public class ResponseFacade implements ServletResponse {
    public ResponseFacade(Response response) {
        this.resp = response;
        this.response = (ServletResponse) response;
    }
    protected ServletResponse response = null;
    protected Response resp = null;
    public String getCharacterEncoding() {
        return response.getCharacterEncoding();
    }
    ......
}
public final class HttpResponseFacade
    extends ResponseFacade
    implements HttpServletResponse {
    public HttpResponseFacade(HttpResponse response) {
        super(response);
    }
    public void addCookie(Cookie cookie) {
        if (isCommitted())
            return;
        ((HttpServletResponse) response).addCookie(cookie);
    }
    ......
}


从这上面可以看出,在tomcat中数据流都是以http协议来进行传输的,不管是ResponseFacade还是HttpResponseFacade中每个方法的实际执行者都是HttpServletResponse。


5、StringManager管理信息,处理国际化问题。
在tomcat中提示消息和输出错误消息都是通过StringManager来管理的,而且还实现了模式的匹配问题,具体如下:
public class StringManager {
    private ResourceBundle bundle;  
    private StringManager(String packageName) ;
    public String getString(String key);
    protected String getStringInternal(String key) ;
    public String getString(String key, Object[] args); 
    public String getString(String key, Object arg) ;
    public String getString(String key, Object arg1, Object arg2);
    public String getString(String key, Object arg1, Object arg2,
                            Object arg3);
    public String getString(String key, Object arg1, Object arg2,
                            Object arg3, Object arg4) ;
    private static Hashtable managers = new Hashtable();
    public synchronized static StringManager getManager(String packageName);
}


6、Jndi的应用,处理资源问题。
这部分我还没有搞的清楚。

7、tomcat的启动框架。
这部分我只能说个大概,主要参考tomcat文档。
<Server>
    <Listener/>
    <GlobalNamingResources/>
    <Service>
        <Connector/>
        <Engine/>
        <Logger/>
        <Realm/>
        <Host>
            <Logger/>
            <Context>
                <Logger/>
            </Context>
        </Host>
    </Service>
</Server>


8、Notification模式
这个模式主要是在import javax.management.*中实现的,其具体的实现在mx4j中实现他的具体实现应该和上面的Listener差不多。
其中主要用到的类为:import javax.management.NotificationBroadcasterSupport和import javax.management.Notification。
NotificationBroadcasterSupport是支持类,Notification为封装了具体信息的事件类。[/size][size=12]
分享到:
评论
1 楼 xiebiao110 2009-10-02  
嗯不错,我也在看tomcat6,tomcat4,分模块来分析,确实不错!

相关推荐

Global site tag (gtag.js) - Google Analytics