tomcat8 源码分析 | 组件及启动过程 (3)

进入NioEndpoint类的bind()

/** * Initialize the endpoint. */ @Override public void bind() throws Exception { //使用nio方式监听端口 if (!getUseInheritedChannel()) { serverSock = ServerSocketChannel.open(); socketProperties.setProperties(serverSock.socket()); InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort())); serverSock.socket().bind(addr,getAcceptCount()); } //设置非阻塞 serverSock.configureBlocking(true); //mimic APR behavior ...... //开启selectorPool selectorPool.open(); } start过程

tomcat的start阶段与init阶段相似,都是逐层调用,稍有不同的是在于engine,host,context,wrapper的启动方式;

首先回到Bootstrap的main方法中,继续执行Catalina类的start(),在start()方法中调getServer().start();

调用LifecycleBase类的start()方法,在这个方法中调动StandardServer类实现的startInternal(),在这个类中继续调用service的star()方法,以此类推逐层start调用,直到调用engine的start(),我们看下engine的start()方法,在看下StandardEngine的类图:

在这里插入图片描述

StandardEngine的startInternal()调用ContainerBase的startInternal()

/** * Start this component and implement the requirements * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}. * * @exception LifecycleException if this component detects a fatal error * that prevents this component from being used */ @Override protected synchronized void startInternal() throws LifecycleException { ...... // Start our child containers, if any Container children[] = findChildren(); List<Future<Void>> results = new ArrayList<>(); for (int i = 0; i < children.length; i++) { results.add(startStopExecutor.submit(new StartChild(children[i]))); } ...... }

findChildren()的方法找到的是engine容器的子容器然后在new StartChild(children[i])中调用子类容器的start();使用这种方式依次启动子容器

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxyfj.html