上篇写到StandardService.init()

这个方法做什么呢?一起来看看。

这个类也是实现了Lifecycle

如图。这个图中i表示Interface接口。如Lifecycle,Container,Executor

C表示Class类 如StandardService

C上有一个小A表示Abstract Class抽象类 如LifecycleBase,WebappClassLoaderBase

感觉用这个图来表示继承关系很好,但这个不能显示出实现关系。要用类图才可以。

public class StandardService extends LifecycleMBeanBase implements Service

跑题了。。

StandardService和StandardServer一样也是继承自LifecycleMBeanBase

在StandardService没有init方法。

调用的其实是LifecycleBase这个类的init方法,然后会调用StandardService.initInternal()

主要作用:

Invoke a pre-startup initialization. This is used to allow connectors to bind to restricted ports under Unix operating environments.

调用预启动初始化。这用于允许connectors绑定到Unix操作环境下的受限端口。

执行LifecycleMBeanBase.initInternal()向MBeanServer类进行MBean(service)组件注册

在这个StandardService的initInternal方法中会先判断container是否为空,

如果不为空则执行container.init()注册container组件(这里的Container是:StandardEngine)

1、初始化所有Executors   

其实就是为Executor指定domain,

然后使用StandardThreadExecutor.initInteral()方法

向MBeanServer注册Executor组件(跟server和service调用init()过程一样)

这里的Executor加载的是org.apache.catalina.core.StandardThreadExecutor类

public interface Executor extends java.util.concurrent.Executor, Lifecycle

//这里可以略过。。。。
An object that executes submitted Runnable tasks. This interface provides a
way of decoupling task submission from the mechanics of how each task will be
run, including details of thread use, scheduling, etc. An Executor is normally
used instead of explicitly creating threads. For example, rather than invoking
new Thread(new(RunnableTask())).start() for each of a set of tasks, you might
use:
执行提交Runnable任务的对象。该接口提供了一种将任务提交从每个任务的运行机制分解的
方法,包括线程使用,调度等的细节。通常使用执行程序,而不是显式创建线程。例如,您可以
使用以下各项来调用每个新任务
 Executor executor = anExecutor;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());
... However, the Executor interface does not strictly require that execution be
asynchronous. In the simplest case, an executor can run the submitted task
immediately in the caller's thread:
Executor接口并不严格要求执行是异步的。在最简单的情况下,执行程序可以立即在调用者的线程中运行提交的任务:
class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}}
More typically, tasks are executed in some thread other than the caller's
thread. The executor below spawns a new thread for each task.
class ThreadPerTaskExecutor implements Executor {
public void execute(Runnable r) {
new Thread(r).start();
}
}}
Many Executor implementations impose some sort of limitation on how and
when tasks are scheduled. The executor below serializes the submission of
tasks to a second executor, illustrating a composite executor.
更通常地,任务在除调用者的线程之外的一些线程中执行。下面的执行器为每个任务生成一个新的线程。
class SerialExecutor implements Executor {
final Queue tasks = new ArrayDeque();
final Executor executor;
Runnable active; SerialExecutor(Executor executor) {
this.executor = executor;
} public synchronized void execute(final Runnable r) {
tasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (active == null) {
scheduleNext();
}
} protected synchronized void scheduleNext() {
if ((active = tasks.poll()) != null) {
executor.execute(active);
}
}
}}
The Executor implementations provided in this package implement
ExecutorService, which is a more extensive interface. The ThreadPoolExecutor
class provides an extensible thread pool implementation. The Executors class
provides convenient factory methods for these Executors.
Memory consistency effects: Actions in a thread prior to submitting a Runnable
object to an Executor happen-before its execution begins, perhaps in another
thread.
此包中提供的Executor实现来实现ExecutorService,它是一个更广泛的接口。
ThreadPoolExecutor类提供了一个可扩展的线程池实现。
Executors类为这些Executors执行人员提供了方便的工厂方法。
内存一致性效果:在将Runnable对象提交给执行程序之前,线程中的操作会在其执行开始之前发生,也许在另一个线程中。

2 、初始化Mapper Listener。调用MapperListener.init()方法,跟上面server,service,executor一样注册组件

3   初始化自定义connectors连接器  Initialize our defined Connectors。

同上调用connector.init()注册connector组件

但在connector.initInteral()方法被重写了

代码不长就贴出来吧

@Override
protected void initInternal() throws LifecycleException { super.initInternal(); // 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()));
} try {
protocolHandler.init();
} catch (Exception e) {
throw new LifecycleException
(sm.getString
("coyoteConnector.protocolHandlerInitializationFailed"), e);
}
}

初始化CoyoteAdapter

Implementation of a request processor which delegates委托 the processing to a Coyote processor

执行将处理委托给CoyoteAdapter的请求处理器

ProtocolHandler protocolHandler端口处理程序

摘要协议实现,包括线程等。ProtocolHandler 处理器是单线程的,

特定于基于流的协议,不适合像JNI这样的Jk协议。这是由CoyoteAdapter实现的主要接口。

adapter是由coyote servlet container.实现的主要接口。

这个ProtocolHandler是一个接口,调用的ProtocolHandler.init()方法的类是org.apache.coyote.http11.Http11NioProtocol

Note:这里不是用Http11Protocol进行处理,我这个tomcat8.0版本是使用Http11NioProtocol处理器

在Connector构造方法中通过protocolHandlerClassName这个变量来生成处理程序实例

connecto被创建会先设置端口处理程序setProtocol()

这里处理http协议请求的有两个处理器

Http11AprProtocol和Http11NioProtocol前者需要安装复杂环境,后者为默认处理器
/**
* Coyote Protocol handler class name.
* Defaults to the Coyote HTTP/1.1 protocolHandler.
*/
protected String protocolHandlerClassName =
"org.apache.coyote.http11.Http11NioProtocol";
public Connector(String protocol) {
  setProtocol(protocol);   Class<?> clazz = Class.forName(protocolHandlerClassName);
  p = (ProtocolHandler) clazz.newInstance();//生成实例 } public void setProtocol(String protocol) { if (AprLifecycleListener.isAprAvailable()) {
if ("HTTP/1.1".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11AprProtocol");
} else if ("AJP/1.3".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.ajp.AjpAprProtocol");
} else if (protocol != null) {
setProtocolHandlerClassName(protocol);
} else {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11AprProtocol");
}
} else {
if ("HTTP/1.1".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11NioProtocol");
} else if ("AJP/1.3".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.ajp.AjpNioProtocol");
} else if (protocol != null) {
setProtocolHandlerClassName(protocol);
}
} }

初始化protocolHandler也就是调用Http11NioProtocol的init方法

public abstract class AbstractProtocol<S> implements ProtocolHandler , MBeanRegistration

有上面可以知道AbstractProtocol实现的ProtocolHandler

--》实际调用

@Override
public void init() throws Exception {
// SSL implementation needs to be in place before end point is
// initialized
必须在end point被初始化之前创建SSL
sslImplementation = SSLImplementation.getInstance(sslImplementationName);
super.init();
}
// Component not pre-registered so register it注册protocolHandler组件
Registry.getRegistry(null, null).registerComponent(this, oname,
null);
//创建thread pool线程池的MBean的名称
tpOname = new ObjectName(domain + ":" +
"type=ThreadPool,name=" + getName());
getName()获得的名字是prefix-address-port
//注册线程池组件
Registry.getRegistry(null, null).registerComponent(endpoint,
tpOname, null);
//Name of MBean for the Global Request Processor.
//注册GlobalRequestProcessor全局请求处理器组件
rgOname=new ObjectName(domain +
":type=GlobalRequestProcessor,name=" + getName());
Registry.getRegistry(null, null).registerComponent(
getHandler().getGlobal(), rgOname, null );
String endpointName = getName();
endpoint.setName(endpointName.substring(, endpointName.length()-));
这里从1开始length-1结束是为了去掉首尾双引号
endpoint.init();

这里执行endpoint是执行的NioEndpoint.init()方法-------在Http11NioProtocol构造方法中设置

public Http11NioProtocol() {
endpoint=new NioEndpoint();
cHandler = new Http11ConnectionHandler(this);
((NioEndpoint) endpoint).setHandler(cHandler);
setSoLinger(Constants.DEFAULT_CONNECTION_LINGER);
setSoTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
setTcpNoDelay(Constants.DEFAULT_TCP_NO_DELAY);
}
NioEndpoint这个类解释
NIO tailored thread pool, providing the following services:
•Socket acceptor thread
•Socket poller thread
•Worker threads pool
When switching to Java 5, there's an opportunity to use the virtual machine's
thread pool.
NIO定制的线程池,提供以下服务:
•套接字线程
•套接字轮询线程
•工作线程池
切换到Java 5时,有机会使用虚拟机的线程池。

NioEndpoint.init()没有重写父类的方法----调用

public final void init() throws Exception {
testServerCipherSuitesOrderSupport();
if (bindOnInit) {
bind();
bindState = BindState.BOUND_ON_INIT;
}
}

parameter:bindOnInit:默认为true

Controls when the Endpoint binds the port.控制endpoint绑定端口

true, the default binds the port on init() and unbinds it on destroy().

If set to false the port is bound on start() and unbound on stop().

NioEndpoint.bind()

/**
* Initialize the endpoint.
*/
@Override
public void bind() throws Exception {
面向流的listening socket的可选通道,新创建的服务器套接字通道已打开但尚未绑定。
调用未绑定服务器套接字通道的accept方法的尝试将导致抛出NotYetBoundException。
可以通过调用此类定义的bind方法来绑定服务器套接字通道
serverSock = ServerSocketChannel.open();
socketProperties.setProperties(serverSock.socket());
//实现了ip套接字地址
InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
serverSock.socket().bind(addr,getBacklog());
serverSock.configureBlocking(true); //mimic APR behavior
serverSock.socket().setSoTimeout(getSocketProperties().getSoTimeout()); // Initialize thread count defaults for acceptor, poller
初始化线程计数器
if (acceptorThreadCount == 0) {
// FIXME: Doesn't seem to work that well with multiple accept threads
acceptorThreadCount = 1;
}
if (pollerThreadCount <= 0) {
//minimum one poller thread
pollerThreadCount = 1;
}
stopLatch = new CountDownLatch(pollerThreadCount); // Initialize SSL if needed
if (isSSLEnabled()) {
SSLUtil sslUtil = handler.getSslImplementation().getSSLUtil(this); sslContext = sslUtil.createSSLContext();
sslContext.init(wrap(sslUtil.getKeyManagers()),
sslUtil.getTrustManagers(), null); SSLSessionContext sessionContext =
sslContext.getServerSessionContext();
if (sessionContext != null) {
sslUtil.configureSessionContext(sessionContext);
}
// Determine which cipher suites and protocols to enable
enabledCiphers = sslUtil.getEnableableCiphers(sslContext);
enabledProtocols = sslUtil.getEnableableProtocols(sslContext);
} if (oomParachute>0) reclaimParachute(true);
selectorPool.open();
}

到这里在Catalina.load()方法中调用的server.init()已经执行完成。

接下来将调用Catalina.start()方法来调用server.start()启动服务

附:
ObjectName代表一个在domain域下的一个对象名称,或者一个正则对象,这个对象可以通过正则上下文来查询

tpOname = new ObjectName(domain + ":" +"type=ThreadPool,name=" + getName());

分为三部分:域名,property list属性列表,属性名key

domain:type=ProtocolHandler,port=
提供底层网络I / O的端点必须与ProtocolHandler实现(ProtocolHandler使用BIO,需要BIO端点等)匹配
 

tomcat启动(五)Catalina分析-service.init的更多相关文章

  1. tomcat启动(四)Catalina分析-server的init()方法

    上一回load()方法解析讲到xml解析完成. load()内部接下来会获取server getServer().setCatalina(this); 这个server从createStartDige ...

  2. tomcat启动(六)Catalina分析-StandardServer.start()

    从链接 Tomcat中组件的生命周期管理公共接口Lifecycle 可以知道调用的是StandardServer.startInternal() @Override protected void st ...

  3. tomcat启动(三)Catalina分析-load方法分析

    load()方法按从上到下顺序分析(主要分析本人所没学过的知识点,其它略过...). Digester类作用 使用sax技术对xml进行解析 未开始解析时Digester.push(this)这个用来 ...

  4. [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat

    概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...

  5. tomcat启动(三)Catalina简要分析

    上篇解析Bootstrap到 daemon.setAwait(true); daemon.load(args); daemon.start(); 这三个方法实际是反射调用org.apache.cata ...

  6. tomcat启动批处理——catalina.bat

    这个批处理才是tomcat服务器启动跟关闭的核心脚本.其中包括....(各种变量),此节将详细讲解这个批处理的逻辑. 先看看第一部分脚本: ****************************** ...

  7. Tomcat启动脚本catalina.sh

    1 - 概述脚本catalina.sh用于启动和关闭tomcat服务器,是最关键的脚本另外的脚本startup.sh和shutdown.sh都是使用不同的参数调用了该脚本该脚本的使用方法如下(引自该脚 ...

  8. ubuntu下tomcat启动巨慢分析

    在一个ubuntu14新环境部署tomcat,通过CI启动一个应用时,启动耗时达到15分钟之久.仔细看tomcat输出的耗时统计日志发现如下日志: Creation of SecureRandom i ...

  9. tomcat启动(Ⅶ)请求处理--Processor.process(SocketWrapper<S> socketWrapper)

    tomcat启动(六)Catalina分析-StandardServer.start() 上一篇分析到:Http11NioProcessor.process(SocketWrapper<S> ...

随机推荐

  1. 发个招聘贴,魔都求手游C++后端,UNITY前端,开发实习生

    上海游旺网络科技有限公司成立于2015年5月,是一家极具潜力的新创移动游戏公司.公司初创团队均来自腾讯,盛大,畅游,墨麟,蜗牛等知名互联网公司,公司创始人团队参与制作过<鬼吹灯><Q ...

  2. 一句话为当前窗口客户区捉图: GetFormImage 来自万一的博客

    一句话为当前窗口客户区捉图: GetFormImage http://www.cnblogs.com/del/archive/2008/10/24/1318738.html unit Unit1; i ...

  3. c# readkey readline read 区别

    Console.read().Console.readline().Console.readkey()和Console.Write.Console.Writeline()的区别 Console.rea ...

  4. eclipse创建Maven工程没有Maven Dependencies

    记一次eclipse创建Maven工程没有Maven Dependencies的坑 Eclipse版本:luna版 maven用的3.5.0 配置本文不提. 这辆天用Eclipse创建maven工程 ...

  5. sqlserver插入之字符串+数字

    declare @i int,@a varchar(10)set @i = 0set @a='hiro--'+LTRIM(@i)while @i < 500begin insert into h ...

  6. 我所理解的网络游戏<?>:战斗逻辑设计

    客户端发送消息,统一在服务器端触发战斗 服务器端驱动战斗过程 客户端端接收用户输入向服务器发送消息 客户端接收服务器消息显示客户端表现   1. 服务器--客户端交互(战斗流程) 整战斗流程分为4个状 ...

  7. LinkedBlockingQueue源码解析(1)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 1.对于LinkedBlockingQueue需要掌握以下几点 创建 入队(添加元素) 出队(删除元素) 2 ...

  8. 全球第一开源云ERP Odoo操作手册 模块安装和界面汉化指南

    之前介绍了odoo的安装和初始设置以及数据库,下面来介绍odoo的模块安装和界面汉化. 1.4 模块安装和界面汉化 Odoo 的功能包含在不同的模块中, 刚创建的数据库除 Odoo 的核心模块外, 其 ...

  9. Struts2乱码问题的解决办法

    乱码问题的起因在于数据在web系统的各个层中间传递的时候编码不同,比如页面使用GB18030而中间层使用UTF-8.由于struts2默认使用的就是UTF-8编码,所以在页面如果使用的是其他的编码格式 ...

  10. H - The LCIS on the Tree HDU - 4718

    The LCIS on the Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Oth ...