引言 本篇文章从一段代码开始,Catalina类中的laod()方法中:
1 2 3 4 5 6 7 8 9 10 11 12 13 try { 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中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public final synchronized void init () throws LifecycleException { 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方法 1 2 3 4 5 6 7 8 9 10 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 1 2 3 4 5 6 protected void fireLifecycleEvent (String type, Object data) { LifecycleEvent event = new LifecycleEvent (this , type, data); for (LifecycleListener listener : lifecycleListeners) { listener.lifecycleEvent(event); } }
最后会依次调用组件的监听者,找个简单的例子VersionLoggerListener:
VersionLoggerListener 1 2 3 <Server port ="8005" shutdown ="SHUTDOWN" > <Listener className ="org.apache.catalina.startup.VersionLoggerListener" /> <Server >
这个类实现了LifecycleListener接口,也就是会重写lifecycleEvent方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 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方法 这个方法是模板模式体现,具体由实现者提供:
1 2 3 4 5 6 7 8 9 protected void initInternal () throws LifecycleException { super .initInternal(); for (int i = 0 ; i < services.length; i++) { services[i].init(); } }
最后会调用services的各个init方法,当然套路是一样的,这里的service是StandardService实例。
StandardService的initInternal方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 protected void initInternal () throws LifecycleException { super .initInternal(); if (engine != null ) { engine.init(); } for (Executor executor : findExecutors()) { if (executor instanceof JmxEnabled) { ((JmxEnabled) executor).setDomain(getDomain()); } executor.init(); } mapperListener.init(); synchronized (connectorsLock) { for (Connector connector : connectors) { connector.init(); } } }
代码不用注释也能看懂,这里再看engine.init与connector.init()
StandardEngine的initInternal方法 1 2 3 4 5 6 7 protected void initInternal () throws LifecycleException { getRealm(); super .initInternal(); }
Connector的initInternal方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 protected void initInternal () throws LifecycleException { super .initInternal(); if (protocolHandler == null ) { throw new LifecycleException ( sm.getString("coyoteConnector.protocolHandlerInstantiationFailed" )); } adapter = new CoyoteAdapter (this ); protocolHandler.setAdapter(adapter); 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 ) { jsseProtocolHandler.setSslImplementationName(OpenSSLImplementation.class.getName()); } } try { protocolHandler.init(); } catch (Exception e) { throw new LifecycleException ( sm.getString("coyoteConnector.protocolHandlerInitializationFailed" ), e); } }
协议的初始化操作。
这篇文章就简单分析了一下Tomcat生命周期的一些套路,还有涉及到的两个设计模式:模板模式与观察者模式。