2019-10-28 17:44  阅读(1979)
文章分类:Tomcat 源码分析 文章标签:TomcatTomcat 源码
©  原文作者:clawhub 原文地址:http://clawhub.club

本篇文章从一段代码开始,Catalina类中的laod()方法中:

        //略......
        // Start the new server
        try {
            //生命周期init方法
            getServer().init();
        } catch (LifecycleException e) {
            if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {
                throw new java.lang.Error(e);
            } else {
                log.error("Catalina.start", e);
            }
        }
        //略......
    

getServer获取的是当前持有的StandardServer,当然调用的init方法也是它的。
具体入口在StandardServer父类LifecycleBase中:

         public final synchronized void init() throws LifecycleException {
                //如果state不是LifecycleState.NEW,执行下面的逻辑
                if (!state.equals(LifecycleState.NEW)) {
                    invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
                }
    
                try {
                    //正在初始化节点
                    setStateInternal(LifecycleState.INITIALIZING, null, false);
                    //具体实例实现
                    initInternal();
                    //初始化结束
                    setStateInternal(LifecycleState.INITIALIZED, null, false);
                } catch (Throwable t) {
                    handleSubClassException(t, "lifecycleBase.initFail", toString());
                }
            }
    

观察者模式的体现

setStateInternal方法

        private synchronized void setStateInternal(LifecycleState state, Object data, boolean check)
                    throws LifecycleException {
               //略......
    
                this.state = state;
                String lifecycleEvent = state.getLifecycleEvent();
                if (lifecycleEvent != null) {
                    fireLifecycleEvent(lifecycleEvent, data);
                }
            }
    

观察者模式的核心,触发生命周期事件:BEFORE_INIT_EVENT、AFTER_INIT_EVENT、START_EVENT、
BEFORE_START_EVENT、AFTER_START_EVENT、STOP_EVENT、BEFORE_STOP_EVENT、AFTER_STOP_EVENT、AFTER_DESTROY_EVENT、
BEFORE_DESTROY_EVENT、PERIODIC_EVENT、CONFIGURE_START_EVENT、CONFIGURE_STOP_EVENT;

fireLifecycleEvent

          protected void fireLifecycleEvent(String type, Object data) {
                LifecycleEvent event = new LifecycleEvent(this, type, data);
                for (LifecycleListener listener : lifecycleListeners) {
                    listener.lifecycleEvent(event);
                }
            }
    

最后会依次调用组件的监听者,找个简单的例子VersionLoggerListener:

VersionLoggerListener

        <Server port="8005" shutdown="SHUTDOWN">
            <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
        <Server>
    

这个类实现了LifecycleListener接口,也就是会重写lifecycleEvent方法:

         public void lifecycleEvent(LifecycleEvent event) {
                if (Lifecycle.BEFORE_INIT_EVENT.equals(event.getType())) {
                    log();
                }
            }
        private void log() {
                log.info(sm.getString("versionLoggerListener.serverInfo.server.version",
                        ServerInfo.getServerInfo()));
                log.info(sm.getString("versionLoggerListener.serverInfo.server.built",
                        ServerInfo.getServerBuilt()));
                log.info(sm.getString("versionLoggerListener.serverInfo.server.number",
                        ServerInfo.getServerNumber()));
                log.info(sm.getString("versionLoggerListener.os.name",
                        System.getProperty("os.name")));
                log.info(sm.getString("versionLoggerListener.os.version",
                        System.getProperty("os.version")));
                log.info(sm.getString("versionLoggerListener.os.arch",
                        System.getProperty("os.arch")));
                log.info(sm.getString("versionLoggerListener.java.home",
                        System.getProperty("java.home")));
                log.info(sm.getString("versionLoggerListener.vm.version",
                        System.getProperty("java.runtime.version")));
                log.info(sm.getString("versionLoggerListener.vm.vendor",
                        System.getProperty("java.vm.vendor")));
                log.info(sm.getString("versionLoggerListener.catalina.base",
                        System.getProperty("catalina.base")));
                log.info(sm.getString("versionLoggerListener.catalina.home",
                        System.getProperty("catalina.home")));
    
                if (logArgs) {
                    List<String> args = ManagementFactory.getRuntimeMXBean().getInputArguments();
                    for (String arg : args) {
                        log.info(sm.getString("versionLoggerListener.arg", arg));
                    }
                }
    
                if (logEnv) {
                    SortedMap<String, String> sortedMap = new TreeMap<>(System.getenv());
                    for (Map.Entry<String, String> e : sortedMap.entrySet()) {
                        log.info(sm.getString("versionLoggerListener.env", e.getKey(), e.getValue()));
                    }
                }
    
                if (logProps) {
                    SortedMap<String, String> sortedMap = new TreeMap<>();
                    for (Map.Entry<Object, Object> e : System.getProperties().entrySet()) {
                        sortedMap.put(String.valueOf(e.getKey()), String.valueOf(e.getValue()));
                    }
                    for (Map.Entry<String, String> e : sortedMap.entrySet()) {
                        log.info(sm.getString("versionLoggerListener.prop", e.getKey(), e.getValue()));
                    }
                }
            }
    

各种的日志打印。也就是说我们也可以自己实现监听器,只有实现LifecycleListener接口,重写lifecycleEvent方法,再配置到Server.xml中即可。

各种initInternal

StandardServer的initInternal方法

这个方法是模板模式体现,具体由实现者提供:

         protected void initInternal() throws LifecycleException {
    
                super.initInternal();
                 //略了
                // Initialize our defined Services
                for (int i = 0; i < services.length; i++) {
                    services[i].init();
                }
            }
    

最后会调用services的各个init方法,当然套路是一样的,这里的service是StandardService实例。

StandardService的initInternal方法

         protected void initInternal() throws LifecycleException {
    
                super.initInternal();
    
                if (engine != null) {
                    engine.init();
                }
    
                // Initialize any Executors
                for (Executor executor : findExecutors()) {
                    if (executor instanceof JmxEnabled) {
                        ((JmxEnabled) executor).setDomain(getDomain());
                    }
                    executor.init();
                }
    
                // Initialize mapper listener
                mapperListener.init();
    
                // Initialize our defined Connectors
                synchronized (connectorsLock) {
                    for (Connector connector : connectors) {
                        connector.init();
                    }
                }
            }
    

代码不用注释也能看懂,这里再看engine.init与connector.init()

StandardEngine的initInternal方法

         protected void initInternal() throws LifecycleException {
                // Ensure that a Realm is present before any attempt is made to start
                // one. This will create the default NullRealm if necessary.
                //Realm域提供了一种用户密码与web应用的映射关系。
                getRealm();
                super.initInternal();
            }
    

Connector的initInternal方法

          protected void initInternal() throws LifecycleException {
                super.initInternal();
                if (protocolHandler == null) {
                    throw new LifecycleException(
                            sm.getString("coyoteConnector.protocolHandlerInstantiationFailed"));
                }
                // Initialize adapter
                adapter = new CoyoteAdapter(this);
                protocolHandler.setAdapter(adapter);
                // Make sure parseBodyMethodsSet has a default
                if (null == parseBodyMethodsSet) {
                    setParseBodyMethods(getParseBodyMethods());
                }
                if (protocolHandler.isAprRequired() && !AprLifecycleListener.isAprAvailable()) {
                    throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoApr",
                            getProtocolHandlerClassName()));
                }
                if (AprLifecycleListener.isAprAvailable() && AprLifecycleListener.getUseOpenSSL() &&
                        protocolHandler instanceof AbstractHttp11JsseProtocol) {
                    AbstractHttp11JsseProtocol<?> jsseProtocolHandler =
                            (AbstractHttp11JsseProtocol<?>) protocolHandler;
                    if (jsseProtocolHandler.isSSLEnabled() &&
                            jsseProtocolHandler.getSslImplementationName() == null) {
                        // OpenSSL is compatible with the JSSE configuration, so use it if APR is available
                        jsseProtocolHandler.setSslImplementationName(OpenSSLImplementation.class.getName());
                    }
                }
                try {
                    protocolHandler.init();
                } catch (Exception e) {
                    throw new LifecycleException(
                            sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
                }
            }
    

协议的初始化操作。

这篇文章就简单分析了一下Tomcat生命周期的一些套路,还有涉及到的两个设计模式:模板模式与观察者模式。


来源:https://www.jianshu.com/u/9632919f32c3

点赞(1)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Tomcat源码分析【六】启动过程分析之生命周期方法init
上一篇
Tomcat源码分析【五】启动过程分析之配置文件解析与组件注入
下一篇
Tomcat源码分析【七】启动过程分析之Server组件的start方法