Tomcat8.5源码分析-StandardHost

StandardHost被启动过程

1.      protected void startInternal() throws LifecycleException {  
2.    
3.          fireLifecycleEvent(CONFIGURE_START_EVENT, null);  
4.          setState(LifecycleState.STARTING);  
5.    
6.          globalNamingResources.start();//JNDI  
7.    
8.          // Start our defined Services  
9.          synchronized (servicesLock) {  
10.             for (int i = 0; i < services.length; i++) {  
11.                 services[i].start();  
12.             }  
13.         }  
14.     }  
这段代码是StandardServer里面的,可以看到,里面启动了services,然后直接转到StandService,然后StandardService的

startInternal启动了StandardEngine代码见下图。

1.  protected void startInternal() throws LifecycleException {  
2.    
3.          if(log.isInfoEnabled())  
4.              log.info(sm.getString("standardService.start.name", this.name));  
5.          setState(LifecycleState.STARTING);  
6.    
7.          // Start our defined Container first  
8.          if (engine != null) {  
9.              synchronized (engine) {  
10.                 engine.start();  
11.             }  
12.         }  

然后再看StandardEngine的startInternal()方法

1.  protected synchronized void startInternal() throws LifecycleException {  
2.    
3.         // Log our server identification information  
4.         if(log.isInfoEnabled())  
5.             log.info( "Starting Servlet Engine: " + ServerInfo.getServerInfo());  
6.    
7.         // Standard container startup  
8.         super.startInternal();  
9.     }  

可以看到这个地方有super.startInternal(); 这个super继承了containerBase这个抽象基础类,这个抽象基础类是container接口的实现,我们可以看一下下面这段代码:

1.  protected synchronized void startInternal() throws LifecycleException {  
2.    
3.          // Start our subordinate components, if any  
4.          //开始下一级的组件,如果有的话  
5.          logger = null;  
6.          getLogger();  
7.          //如果配置了集群组件,则启动  
8.          Cluster cluster = getClusterInternal();  
9.          if (cluster instanceof Lifecycle) {  
10.             ((Lifecycle) cluster).start();  
11.         }  
12.         //如果配置了安全组件,则启动  
13.         Realm realm = getRealmInternal();  
14.         if (realm instanceof Lifecycle) {  
15.             ((Lifecycle) realm).start();  
16.         }  
17.   
18.         // Start our child containers, if any  
19.         //catalina构造server实例时,server.xml中如果存在host的子容器context,调用addChild方法  
20.         Container children[] = findChildren();  
21.         List<Future<Void>> results = new ArrayList<>();  
22.         for (int i = 0; i < children.length; i++) {  
23.             results.add(startStopExecutor.submit(new StartChild(children[i])));  
24.         }  
25.   
26.         boolean fail = false;  
27.         for (Future<Void> result : results) {  
28.             try {  
29.                 result.get();  
30.             } catch (Exception e) {  
31.                 log.error(sm.getString("containerBase.threadedStartFailed"), e);  
32.                 fail = true;  
33.             }  
34.   
35.         }  
36.         if (fail) {  
37.             throw new LifecycleException(  
38.                     sm.getString("containerBase.threadedStartFailed"));  
39.         }  
40.   
41.         // Start the Valves in our pipeline (including the basic), if any  
42.         //启动host所持有的Pipeline组件  
43.         if (pipeline instanceof Lifecycle)  
44.             ((Lifecycle) pipeline).start();  
45.   
46.   
47.         // Start our thread  
48.         //开始线程,启动后台线程  
49.         threadStart();  
50.   
51.     }  
  1. 关注这一句results.add(startStopExecutor.submit(new StartChild(children[i])));这个地方用了线程的submit方法,看下面这段代码:
private static class StartChild implements Callable<Void> {  
2.    
3.         private Container child;  
4.    
5.         public StartChild(Container child) {  
6.             this.child = child;  
7.         }  
8.    
9.         @Override  
10.        public Void call() throws               LifecycleException {  
11.            child.start();/*在这个地方调用的*/  
12.            return null;  
13.        }  
14.    }  

这是StartChild类,可以看到他实现了callable接口,当线程使用submit方法时,call()方法会被调用,子容器将会调用start方法,即child.start(),在这个地方启动了StandardHost。而且result是一个数组,遍历启动子容器,就是说一个容器可以启动多个子容器,如一个StandardEngine可以有多个StandardHost。可以看到catalina的架构图很明显表明了这一点。
StandardHost源码分析(部分)

1.  protected synchronized void startInternal() throws LifecycleException {  
2.    
3.          // Set error report valve  
4.          //该类主要用于Tomcat发生异常时输出错误页面  
5.          String errorValve = getErrorReportValveClass();  
6.          //查看pipleLine里是否有error report valve  
7.          if ((errorValve != null) && (!errorValve.equals(""))) {  
8.              try {  
9.                  boolean found = false;  
10.                 Valve[] valves = getPipeline().getValves();  
11.                 for (Valve valve : valves) {  
12.                     if (errorValve.equals(valve.getClass().getName())) {  
13.                         found = true;  
14.                         break;  
15.                     }  
16.                 }  
17.                 if(!found) {  
18.                     Valve valve =  
19.                         (Valve) Class.forName(errorValve).getConstructor().newInstance();/*如果没有找到利用反射创建对象*/  
20.                     getPipeline().addValve(valve);/*把valve加到管道里*/  
21.                 }  
22.             } catch (Throwable t) {  
23.                 ExceptionUtils.handleThrowable(t);  
24.                 log.error(sm.getString(  
25.                         "standardHost.invalidErrorReportValveClass",  
26.                         errorValve), t);  
27.             }  
28.         }  
29.         super.startInternal();//启动虚拟主机,转到了ContainBase  
30.     }  

可以看到,这个启动方法里面就只是做了两件事:
1.添加了一个ErrorReportValve
2.调用containerBase.StartInternal()
关于containerBase.StartInternal()方法,前面已经添加了代码和注释,不在赘述。
此时有两种情况
1.catalina构造server实例时,server.xml中如果存在host的子容器context,调用addChild方法,此时直接调用StandardContext.Start()
2.没有子容器context,触发fireLifeCycleEvent(),转到HostConfig。

把lifecycle的状态改变了。而此时有监听器,setState是基础抽象类lifecycleBase的方法,我们看一下它的相关代码。
setState:

1.  protected synchronized void setState(LifecycleState state)  
2.              throws LifecycleException {  
3.          setStateInternal(state, null, true);  
4.      }  
在看这个setStateInternal:
1.  private synchronized void setStateInternal(LifecycleState state,  
2.              Object data, boolean check) throws LifecycleException {  
3.    
4.          if (log.isDebugEnabled()) {  
5.              log.debug(sm.getString("lifecycleBase.setState", this, state));  
6.          }  
7.    
8.          if (check) {  
9.              // Must have been triggered by one of the abstract methods (assume  
10.             // code in this class is correct)  
11.             // null is never a valid state  
12.             if (state == null) {  
13.                 invalidTransition("null");  
14.                 // Unreachable code - here to stop eclipse complaining about  
15.                 // a possible NPE further down the method  
16.                 return;  
17.             }  
18.   
19.             // Any method can transition to failed  
20.             // startInternal() permits STARTING_PREP to STARTING  
21.             // stopInternal() permits STOPPING_PREP to STOPPING and FAILED to  
22.             // STOPPING  
23.             if (!(state == LifecycleState.FAILED ||  
24.                     (this.state == LifecycleState.STARTING_PREP &&  
25.                             state == LifecycleState.STARTING) ||  
26.                     (this.state == LifecycleState.STOPPING_PREP &&  
27.                             state == LifecycleState.STOPPING) ||  
28.                     (this.state == LifecycleState.FAILED &&  
29.                             state == LifecycleState.STOPPING))) {  
30.                 // No other transition permitted  
31.                 invalidTransition(state.name());  
32.             }  
33.         }  
34.   
35.         this.state = state;  
36.         String lifecycleEvent = state.getLifecycleEvent();  
37.         if (lifecycleEvent != null) {  
38.             fireLifecycleEvent(lifecycleEvent, data);  
39.         }  
40.     }  

可以在看到在最后触发了这个生命周期事件。

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

在Digester创建对象时,listener为HostConfig。
接下来我们分析HostConfig的代码。
Tomcat8.5源码分析-HostConfig

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值