Tomcat源码分析【六】启动过程分析之生命周期方法init

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

文章首发于: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

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Tomcat源码分析【六】启动过程分析之生命周期方法init

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏