双亲委托类加载机制_浅析tomcat7类加载机制及初始化流程

文章背景,之前看springmvc源码,虽然了解了servlet的执行过程,但是对于servlet的出处却不知道,不清楚jsp是怎么初始化的,只能下载tomcat源码看看,并未买书系统学习,所以不会太深

1.tomcat类加载机制设计图

6f195d7c384a98e5422281a874b609a0.png

commonLoader:Tomcat最基本的类加载器,加载路径中的class可以被Tomcat容器本身以及各个Webapp访问;

catalinaLoader:Tomcat容器私有的类加载器,加载路径中的class对于Webapp不可见;

sharedLoader:各个Webapp共享的类加载器,加载路径中的class对于所有Webapp可见,但是对于Tomcat容器不可见;

WebappClassLoader:各个Webapp私有的类加载器,加载路径中的class只对当前Webapp可见;

2.传统双亲委派模型类加载顺序

91ccb66385469714fddfd02cf42500cb.png

3.如果parent需要加载子类怎么实现

场景:如果十个web应用都引入了spring的类,由于web类加载器的隔离,那么对内存的开销是很大的。此时我们可以想到shared类加载器,我们肯定都会选择将spring的jar放于shared目录底下,但是此时又会存在一个问题,shared类加载器是webapp类加载器的parent,若spring中的getBean方法需要加载web应用底下的类,这种过程是违反双亲委托机制的。

方案:线程上下文类加载器是指的当前线程所用的类加载器,可以通过Thread.currentThread().getContextClassLoader()获得或者设置,在spring中,他会选择线程上下文类加载器去加载web应用底下的类,在web.xml中定义的listener为org.springframework.web.context.ContextLoaderListener,它最终调用了org.springframework.web.context.ContextLoader类来装载bean,代码如下

this.contextLoader.initWebApplicationContext(event.getServletContext());

//下面逻辑判断类加载器是否相同,不同则赋值

ClassLoader ccl = Thread.currentThread().getContextClassLoader();

if (ccl == ContextLoader.class.getClassLoader()) {

currentContext = this.context;

}else if (ccl != null) {

currentContextPerThread.put(ccl, this.context);

}

4.tomcat7各个加载器分别加载的文件

具体可查看catalina.properties的配置

common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jarcatalinaLoader:$CATALINA_BASE/bin

sharedLoader:可以自行配置

webappClassLoader:

web application下的/WEB_INF/classes

web application下的/WEB_INF/lib/*.jar

1.启动类:Bootstrap.main()

2.项目运行时加载静态方法

CatalinaProperties.loadProperties();加载conf/catalina.properties文件,放入到System.setProperty();

3.Bootstrap.initClassLoaders()类加载

3.1 读取catalina.properties中属性:common.loader,将属性指定的的tomcat/lib目录下的所有jar包全路径加载到

ClassLoader commonLoader = createClassLoader(“common”, null);

3.2 读取catalina.properties中属性:server.loader,如果没配置,则返回ClassLoader catalinaLoader=commonLoader;

3.3 读取catalina.properties中属性:shared.loader,如果没配置,则返回ClassLoader sharedLoader=commonLoader;

4.Catalina.load()容器初始化

4.1 Digester digester = createStartDigester();设定service.xml解析规则;

digester.parse(inputSource);将servive.xml文件解析成java对象;

4.2 容器初始化

getServer().init();–》

LifecycleBase.init()–》

StandardServer.initInternal()–》

services[i].init();–》

LifecycleBase.init()–》

StandardService.initInternal()–》

引擎初始化:engine.init();–》

LifecycleBase.init()–》

StandardEngine.initInternal()

端口监听初始化:connector.init();–》

LifecycleBase.init()–》

Connector.initInternal()–》

protocolHandler.init(); --》

endpoint.init();–》

AbstractJsseEndpoint.init()–》

AbstractEndpoint.init()–》

NioEndpoint.bind();

4.3时序图参考

29b602836fb75c3ec119bb5bd54782fd.png

5.nio模型,参考博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值