2、Bootstrap启动流程
2023-07-26 08:38:33 17 举报
Bootstrap是Spring框架的引导程序,它负责启动整个Spring应用程序。Bootstrap启动流程主要包括以下几个步骤: 1. 加载Spring配置文件。 2. 扫描并解析配置类,将其注册为Bean。 3. 根据Bean的定义创建对象并进行属性注入。 4. 调用Bean的初始化方法进行初始化操作。 5. 将初始化完成的Bean放入缓存中,等待使用。 以上就是Bootstrap启动流程的简要描述。
作者其他创作
大纲/内容
StandardEngine
initInternal()
1、设置连接器生命周期状态为start2、调用protocolHandler的start方法
AbstractProtocol
1、标记loaded=true2、设置naming系统变量,配置JNDI初始化上下文工厂类3、Digester实例解析server.xml,工作量巨大,很核心4、获取StandarServer实例,设置基本信息5、重定向控制台out和err输出流到指定的日志处理handler类6、调用server的init方法
1、先调用父类LifecycleMBeanBase重写的initInternal方法,完成service bean的注册2、一个service对应一个servlet engine,初始化engine3、一个service对应多个线程池,如果配置有,循环初始化executor4、初始化mapperListener,这个重点记住5、一个service对应多个connector,循环初始化connector
主要就是调用父类ContainerBase的startInternal方法,依次:1、如果配置的有realm,则启动安全域容器2、如果含有Host子容器,则遍历构建子容器启动异步任务(StartChild 实现了Callable接口,这是一个递归操作,因为子容器可能还包括子容器,这个分层的架构爱了),交由线程池执行,容器中的线程池复用了Server中的线程池。然后阻塞获取各容器启动的状态,如果异常则抛出!3、启动容器的管道4、上面都完成后,设置自身的生命周期状态为start总结:容器部分的启动是最令人兴奋的,很精彩!(StandardHost、StandardContext和StandardWrapper没有画出来,主要调用过程跟Engine的一样,就不画了)
Connector默认走的协议是HTTP/1.1,其对应的协议处理器是HTTP11NioProtocol,这个协议借助了NioEndPoint实现请求接收和数据读取处理,protocolHandler的适配器是CoyoteAdapter
1、发布configure_start事件2、更新生命周期状态为start3、启动全局命名资源组件4、遍历Services组件,逐一启动(默认就一个个,我们也不需要配置多个)
Catalina
反射调用Catalina类的setParentClassLoader方法
将上一步实例化好的adapter设置到handler
最后调用protocolHandler的init方法,这个方法很重要,很核心
AbstractEndpoint
*
ProtocolHandler(接口)
内部牵扯生命周期状态改变引起的监听器遍历调用,这一步就省略了,包括后面的MBean注册功能等也一样省略!
所有tomcat组件都实现了这个接口,也就是组件是有生命周期的,如初始化、启动、停止、销毁等。
1、初始化类加载器,主要有三个,如右图2、设置线程上下文类加载为catalinaLoader3、通过反射实例化Catalina对象,并设置Catalina模块中的容器的类加载器为sharedLoader
new CoyoteAdapter(connector)
Connector
init()
StandardServer
load()
start()
Bootstrap
这个是NIO中很经典的一段代码了
先调StandardServer父接口的init方法
startInternal()
AbstractProtocol初始化工作,主要就是注册MBean及配置NioEndpoint对象的属性,比如设置name、设置domain等,然后重头戏就是调用NioEndpoint的init方法
setAdapter(adapter)
setParentClassLoader()
2、循环初始化连接器connector
Acceptor就是一个单线程,循环处理客户端连接的,然后扔给endpoint对象中的poller进行注册,也就是acceptor接收到socket连接,然后交给endpoint对象处理,endpoint对象拿到socket后,将其包装成NioSocketWrapper对象,然后再基于该对象包装成pollerEvent,添加到poller线程中的事件同步队列中,然后poller(里面持有一个selector对象)轮训IO就绪事件(当然这个是阻塞的),一旦有就绪event,就调用processKey方法,processKey的业务逻辑就是把准备就绪的IO事件(一般为读,因为请求过来了,要读取请求中的信息,也就是读取request)扔给线程池来处理,当然还得有专门的SocketProcessor线程处理才行,最后线程执行是有线程池来管理的。
startIntenal()
1、先调用父类LifecycleMBeanBase重写的initInternal方法,完成server bean的注册2、将全局jndi服务注册到MBeanServer3、递归验证公共jar和共享jar是否含有manifest,不符合要求的jar将会被\"剔除\"4、遍历service组件,依次调用service的init方法
生命周期接口实现抽象类,模板方法,封装算法,并实现部分算法逻辑
StandardService
initServerSokcet()
初始化endpoint,主要做了三件事情:1、初始化服务器套接字2、初始化endpoint停止工作的锁栓对象3、初始化SSL
继承
CoyoteAdapter
初始化服务端套接字至此,整个Bootstrap的load方法调用链条完毕!!!
1、判断server==null,如果是,走一遍server.load()方法2、调用server的start()方法3、Catalina主线程阻塞,直到Server接收到SHUTDOWM命令后,调用stop()方法!!!
Lifecyclebase
ProtocolHandler的init方法调用,实际上调用的是其子类AbstractProtocol实现的init方法,这里只是告诉你,AbstractProtocol是一个ProtocolHandler类型的
判断protocalHandler,如果为空,抛异常
AbstractHttp11Protocol
ProtocolHandler
实现
1
font color=\"#323232\
LifycycleBase
1、更新生命周期状态为start2、启动engine3、如果xml配置了线程池,则启动Tomcat线程池(也是一个生命周期组件),主要就是初始化任务队列、初始化JDK线程池对象等4、启动mapperListener,很重要5、遍历连接器列表,启动connector
1、初始化engine
new Bootstrap()
这个设置父类加载器可不是设置Catalina类加载器的parent,其就是一个成员变量,后面会用于StandardContext类加载器的parent!
NioEndpoint
1、如果Connector没有关联线程池,就创建一个worker executor,反之就使用Service节点中配置的线程池。(核心线程默认是10,最大线程默认是200)2、初始化客户端连接锁栓,默认最大接收的客户端连接数在Tomcat9.0之后是8*1024,之前是10000个3、创建poller线程并启动,poller线程持有一个selector对象,轮询所有的SocketChannel,一旦有IO读事件就绪,就交给woker工作线程池进行处理4、开启Acceptor线程,一个connector对应一个acceptor,acceptor主要负责接收客户端连接
调用实现类LifecycleBase的init方法
bindWithCleanup()
sharedLoader共享类加载器,加载不同应用之间共享的依赖jar
engine的初始化,主要是获取realm对象,Realm是底层安全领域的只读外观,用于对单个用户进行身份验证,并标识与这些用户关联的安全角色。领域可以附加在任何容器级别,但通常只会附加到上下文或更高级别的容器。(补充:类似于unix组),另外也少不了注册MBean
模板方法,init方法内部又调用了initInternal方法,initInternal方法是抽象的,子类必须实现
默认实现的子类是:Http11NioProtocol
实例化adapter
catalinaLoader加载catalina模块下面的jar
bind()
反射调用Catalina类的load方法
commonLoader加载tomcat依赖的jar,比如servlet-api
Lifecycle
Lifecycle(接口)
0 条评论
下一页