您的位置:首页 > 运维架构 > Tomcat

tomcat解析(十)StandardService.initialize.start

2010-02-02 18:04 323 查看
先上代码:

一.initialize

/**
* Invoke a pre-startup initialization. This is used to allow connectors
* to bind to restricted ports under Unix operating environments.
*/
public void initialize()
throws LifecycleException
{
// Service shouldn't be used with embeded, so it doesn't matter
if (initialized) {
if(log.isInfoEnabled())
log.info(sm.getString("standardService.initialize.initialized"));
return;
}
initialized = true;
if( oname==null ) {
try {
// Hack - Server should be deprecated...
Container engine=this.getContainer();
domain=engine.getName();
oname=new ObjectName(domain + ":type=Service,serviceName="+name);
this.controller=oname;
Registry.getRegistry(null, null)
.registerComponent(this, oname, null);

Executor[] executors = findExecutors();
for (int i = 0; i < executors.length; i++) {
ObjectName executorObjectName =
new ObjectName(domain + ":type=Executor,name=" + executors[i].getName());
Registry.getRegistry(null, null)
.registerComponent(executors[i], executorObjectName, null);
}

} catch (Exception e) {
log.error(sm.getString("standardService.register.failed",domain),e);
}

}
if( server==null ) {
// Register with the server
// HACK: ServerFactory should be removed...

ServerFactory.getServer().addService(this);
}

// Initialize our defined Connectors
synchronized (connectors) {
for (int i = 0; i < connectors.length; i++) {
connectors[i].initialize();
}
}
}


主要的内容有三部分:

1.Registry.getRegistry(null, null).registerComponent(executors[i], executorObjectName, null);

使用MBean注册组件

2.ServerFactory.getServer().addService(this);

ServerFactory.getServer()返回的对象为StandardServer对象,而在实例化StandardService时已经调用了该方法进行设置了,因此这里其它是做多了一次设置

3.connectors[i].initialize();

分别调用所有connectors的initialize()方法,该方法如下:

/**
* Initialize this connector (create ServerSocket here!)
*/
public void initialize()
throws LifecycleException
{
if (initialized) {
if(log.isInfoEnabled())
log.info(sm.getString("coyoteConnector.alreadyInitialized"));
return;
}
this.initialized = true;
if( oname == null && (container instanceof StandardEngine)) {
try {
// we are loaded directly, via API - and no name was given to us
StandardEngine cb=(StandardEngine)container;
oname = createObjectName(cb.getName(), "Connector");
Registry.getRegistry(null, null)
.registerComponent(this, oname, null);
controller=oname;
} catch (Exception e) {
log.error( "Error registering connector ", e);
}
if(log.isDebugEnabled())
log.debug("Creating name for connector " + oname);
}
// Initializa adapter
adapter = new CoyoteAdapter(this);
protocolHandler.setAdapter(adapter);
IntrospectionUtils.setProperty(protocolHandler, "jkHome",
System.getProperty("catalina.base"));
try {
protocolHandler.init();
} catch (Exception e) {
throw new LifecycleException
(sm.getString
("coyoteConnector.protocolHandlerInitializationFailed", e));
}
}


可看到实例化了adapter对象后,最终调用了protocolHandler.init(),其中protocolHandler对象实例化过程如下:

/**
* Coyote Protocol handler class name.
* Defaults to the Coyote HTTP/1.1 protocolHandler.
*/
protected String protocolHandlerClassName =
"org.apache.coyote.http11.Http11Protocol";
......
public Connector(String protocol)
throws Exception {
setProtocol(protocol);
// Instantiate protocol handler
try {
Class clazz = Class.forName(protocolHandlerClassName);
this.protocolHandler = (ProtocolHandler) clazz.newInstance();
} catch (Exception e) {
log.error
(sm.getString
("coyoteConnector.protocolHandlerInstantiationFailed", e));
}
}


因此这里将调用的是Http11Protocol的方法 ,我们再看Http11Protocol.init到底做了什么事

protected Http11ConnectionHandler cHandler = new Http11ConnectionHandler(this);
protected JIoEndpoint endpoint = new JIoEndpoint();
......
public void init() throws Exception {
endpoint.setName(getName());
endpoint.setHandler(cHandler);
// Verify the validity of the configured socket factory
try {
if (isSSLEnabled()) {
sslImplementation =
SSLImplementation.getInstance(sslImplementationName);
socketFactory = sslImplementation.getServerSocketFactory();
endpoint.setServerSocketFactory(socketFactory);
} else if (socketFactoryName != null) {
socketFactory = (ServerSocketFactory) Class.forName(socketFactoryName).newInstance();
endpoint.setServerSocketFactory(socketFactory);
}
} catch (Exception ex) {
log.error(sm.getString("http11protocol.socketfactory.initerror"),
ex);
throw ex;
}
if (socketFactory!=null) {
Iterator<String> attE = attributes.keySet().iterator();
while( attE.hasNext() ) {
String key = attE.next();
Object v=attributes.get(key);
socketFactory.setAttribute(key, v);
}
}

try {
endpoint.init();
} catch (Exception ex) {
log.error(sm.getString("http11protocol.endpoint.initerror"), ex);
throw ex;
}
if (log.isInfoEnabled())
log.info(sm.getString("http11protocol.init", getName()));
}


前一部分是在设置endpoint对象的属性,最后调用其Init方法,如下:

public void init()
throws Exception {
if (initialized)
return;

// Initialize thread count defaults for acceptor
if (acceptorThreadCount == 0) {
acceptorThreadCount = 1;
}
if (serverSocketFactory == null) {
serverSocketFactory = ServerSocketFactory.getDefault();
}
if (serverSocket == null) {
try {
if (address == null) {
serverSocket = serverSocketFactory.createSocket(port, backlog);
} else {
serverSocket = serverSocketFactory.createSocket(port, backlog, address);
}
} catch (BindException be) {
if (address == null)
throw new BindException(be.getMessage() + "<null>:" + port);
else
throw new BindException(be.getMessage() + " " +
address.toString() + ":" + port);
}
}
//if( serverTimeout >= 0 )
//    serverSocket.setSoTimeout( serverTimeout );

initialized = true;
}


最终产生了一个ServerSocket对象,虽然有ServerSocket,但还需要执行其accept()才能获取客户端请求的,因此这里其实还不能处理请求.

二.start

/**
* Prepare for the beginning of active use of the public methods of this
* component.  This method should be called before any of the public
* methods of this component are utilized.  It should also send a
* LifecycleEvent of type START_EVENT to any registered listeners.
*
* @exception LifecycleException if this component detects a fatal error
*  that prevents this component from being used
*/
public void start() throws LifecycleException {
// Validate and update our current component state
if (log.isInfoEnabled() && started) {
log.info(sm.getString("standardService.start.started"));
}

if( ! initialized )
init();
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
if(log.isInfoEnabled())
log.info(sm.getString("standardService.start.name", this.name));
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
// Start our defined Container first
if (container != null) {
synchronized (container) {
if (container instanceof Lifecycle) {
((Lifecycle) container).start();
}
}
}
synchronized (executors) {
for ( int i=0; i<executors.size(); i++ ) {
executors.get(i).start();
}
}
// Start our defined Connectors second
synchronized (connectors) {
for (int i = 0; i < connectors.length; i++) {
if (connectors[i] instanceof Lifecycle)
((Lifecycle) connectors[i]).start();
}
}

// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}


主要的内容有二部分:

1.lifecycle.fireLifecycleEvent

触发Lifecycle事件,这里没有注册相应的监听器

2.((Lifecycle) container).start();executors.get(i).start();((Lifecycle) connectors[i]).start();

调用了几元素的start方法

这里的container,executors及connectors从何而来呢?

1.executors是需要在server.xml里配置Server/Service/Executor的,如果进行了配置,将产生类型为org.apache.catalina.core.StandardThreadExecutor的对象,并全部放入StandardService的ArrayList<Executor> executors里

2.connectors与executors一样,也要进行配置,路径为Server/Service/Connector,对象类型为:org.apache.catalina.connector.Connector

3.container则需要查看Catalina.createStartDigester里的内容,有一句代码如下:

digester.addRuleSet(new EngineRuleSet("Server/Service/"));

查看EngineRuleSet对象addRuleInstances方法,可看到将添加ObjectCreateRule创建类型为org.apache.catalina.core.StandardEngine的对象,并调用StandardService.setContainer,对象将放入StandardService的container变量里,同时放入Connector的container变量,而该StandardService对象将放入StandardEngine的service变量里,因此这里将调用StandardEngine.start();

这里需要注意的是container.start的调用是在Connector之前的,这样做是有理由的;container.start()里将会为服务器准备所有工程项目的解析及部署工作,而Connector.start()将会让tomcat开始接受并处理用户的请求,因此是需要放在工程部署准备完成之后的,因此Connector.start()我们将放在最后来讲,下一篇目我们讲的是StandardEngine
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐